2011-04-28 104 views
13

我有一個表像some_table的Oracle SQL GROUP BY 「不是一個GROUP BY表達式」 幫助

+--------+----------+---------------------+-------+ 
| 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_id123最新記錄。我想出了明顯的查詢是

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子句中添加所有其他字段(即id,value),但這只是返回所有內容,就好像沒有GROUP BY子句一樣。 (好吧,它也有道理。)

所以......我正在閱讀Oracle SQL手冊,我能找到的只是一些只涉及兩列或三列查詢以及一些我沒有預先分組功能。我如何去和返回

+--------+----------+---------------------+-------+ 
| 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
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 
+1

優秀!這就像一個魅力! – 2011-04-28 08:19:37

+0

爲什麼不使用MAX聚合? – Benoit 2011-04-28 08:22:36

+0

@Benoit,'order by date_value desc'做同樣的事情 – 2011-04-28 08:32:47

8

您不能選擇任何不是聚合的列,也不能選擇僅在GROUP BY子句中使用的列計算的列。

但是有三種方法做到這一點:

  • 您可以使用分析功能

    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) 
    
+0

第一查詢與'MAX_DATE不是一個有效的identifier' – 2011-04-28 08:29:34

+0

@Yanick羅森結束:是的,實際上這個查詢也應該嵌套。我會重寫一下。其他查詢的工作? – Benoit 2011-04-28 08:35:53

+0

是的,第二個工作,但比Michael慢(0.030 ms,平均超過0.010 ms) – 2011-04-28 08:41:23

0

也許這是最簡單的方法

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)); 

Test the above query here