2011-04-28 96 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