【问题标题】:Oracle SQL GROUP BY "not a GROUP BY expression" helpOracle SQL GROUP BY“不是 GROUP BY 表达式”帮助
【发布时间】:2011-08-14 12:12:53
【问题描述】:

我有一张桌子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_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 子句中添加所有其他字段(即idvalue),但这只会返回所有内容,就像没有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 的最新条目)?谢谢。

【问题讨论】:

    标签: sql oracle group-by


    【解决方案1】:

    您不能选择任何既不是聚合也不是仅根据 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 )
      

    【讨论】:

    • 第一个查询以max_date not a valid identifier结束
    • @Yanick Rochon:是的,实际上这个查询也应该嵌套。我会稍微重写一下。其他查询是否有效?
    • 是的,第二个有效,但比迈克尔的慢(平均 0.030 毫秒超过 0.010 毫秒)
    • @Yanick Rochon:难怪,分析函数就是为此目的而设计的。因此,自联接成本更高(但如果您切换到另一个 RDBMS,它仍然可用)。
    【解决方案2】:
     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
    

    【讨论】:

    • 为什么不使用 MAX 聚合?
    • @Benoit,order by date_value desc 做同样的事情
    • @Yanick Rochon:是的,但排序总是有代价的。可能使用MAX 效率更高。
    【解决方案3】:

    可能这是最简单的方法

    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

    【讨论】:

      猜你喜欢
      • 2017-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-04
      • 2014-01-30
      • 2011-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多