web-dev-qa-db-ja.com

Oracle SQL GROUP BY "GROUP BY式ではない"ヘルプ

some_tableのようなテーブルがあります

+--------+----------+---------------------+-------+
| id     | other_id | date_value          | value |
+--------+----------+---------------------+-------+
| 1      | 1        | 2011-04-20 21:03:05 | 104   |
| 2      | 2        | 2011-04-20 21:03:04 | 229   |
| 3      | 3        | 2011-04-20 21:03:03 | 130   |
| 4      | 1        | 2011-04-20 21:02:09 | 97    |
| 5      | 2        | 2011-04-20 21:02:08 | 65    |
| 6      | 3        | 2011-04-20 21:02:07 | 101   |
| ...    | ...      | ...                 | ...   |
+--------+----------+---------------------+-------+

そして、other_id12、および3の最新のレコードが必要です。私が思いついた明白なクエリは

SELECT id, other_id, MAX(date_value), value
  FROM some_table 
 WHERE other_id IN (1, 2, 3) 
 GROUP BY other_id

ただし、「not a GROUP BY expression」例外が発生します。 GROUP BY句に他のすべてのフィールド(つまり、idvalue)を追加してみましたが、GROUP BY句がない場合とまったく同じように、すべてが返されます。 (まあ、それも理にかなっています。)

だから...私はOracle SQLのマニュアルを読んでいて、見つけることができるのは、2つまたは3つの列を含むクエリと、i-have-never-before-beforeなグループ化関数を含むいくつかの例だけです。どうやって行き帰るの?

+--------+----------+---------------------+-------+
| id     | other_id | date_value          | value |
+--------+----------+---------------------+-------+
| 1      | 1        | 2011-04-20 21:03:05 | 104   |
| 2      | 2        | 2011-04-20 21:03:04 | 229   |
| 3      | 3        | 2011-04-20 21:03:03 | 130   |
+--------+----------+---------------------+-------+

(各other_idの最新のエントリ)?ありがとうございました。

14
Yanick Rochon
 select id, other_id, date_value, value from
 (
   SELECT id, other_id, date_value, value, 
   ROW_NUMBER() OVER (partition by other_id order BY Date_Value desc) r
   FROM some_table 
   WHERE other_id IN (1, 2, 3) 
 )
 where r = 1
15

集計ではない列、またはGROUP BY句で使用されている列のみから計算された列を選択することはできません。

ただし、これには3つの方法があります。

  • 分析関数を使用できます

    SELECT id, other_id, date_value, value
      FROM ( SELECT id, other_id, date_value, MAX(date_value) OVER (partition by other_id) max_date, value
               FROM some_table )
     WHERE max_date = date_value;
    
  • 「より大きい」句で自己結合を使用して、この方法で最大値を検出できます

    SELECT t1.id, t1.other_id, t1.date_value, t1.value
      FROM some_table t1
      LEFT OUTER JOIN some_table t2
                   ON ( t1.other_id = t2.other_id AND t2.date_value > t1.date_value )
     WHERE t2.other_id IS NULL
    
  • サブクエリを使用できます

      WITH max AS ( SELECT other_id, MAX(date_value) FROM some_table GROUP BY other_id )
    SELECT id, other_id, date_value, value
      FROM some_table
     WHERE ( other_id, date_value ) IN ( SELECT * FROM max )
    
8
Benoit

おそらくこれが最も簡単な方法です

SELECT id, other_id, date_value, value
FROM some_table
WHERE date_value in (SELECT MAX(date_value)
                     from some_table
                     GROUP BY other_id
                     HAVING other_id in (1,2,3));

上記のクエリをここでテストします

0
Shivanand