【问题标题】:Choose subset of rows grouped by part of a column?选择按列的一部分分组的行子集?
【发布时间】:2014-03-31 15:37:26
【问题描述】:

假设我在一个表中有这些行:

ID | SomeColumn | SomeDateTime
---+------------+-------------
1  | X1         | 01-01-14 14:00:00
2  | X2         | 01-01-14 22:00:00
3  | Y1         | 01-03-14 12:00:00
4  | Y2         | 01-03-14 23:00:00

如何进行 SQL 查询以仅获取具有 不同 日期的行(选择最新时间)?也就是说,查询的结果应该是:

ID | SomeColumn | SomeDateTime
---+------------+-------------
2  | X2         | 01-01-14 22:00:00
4  | Y2         | 01-03-14 23:00:00

我试过了,但它不起作用:

SELECT MAX(SomeDateTime),ID,SomeColumn,SomeDateTime
FROM MyTable GROUP BY (SomeDateTime::date)

我得到的错误是:

The column "MyTable.ID" needs to appear in the GROUP BY clause or be used in an aggregation function

我正在使用 PostgreSQL,但如果您有其他数据库引擎的答案,我也会投票。

【问题讨论】:

    标签: sql database postgresql relational-database greatest-n-per-group


    【解决方案1】:
    SELECT DISTINCT ON (some_datetime::date)
           id, some_column, some_datetime
    FROM   tbl 
    ORDER  BY some_datetime::date, some_datetime DESC;
    

    DISTINCT ON详解:
    Select first row in each GROUP BY group?

    这里稍微特殊的要求是在派生值上形成分区。转换为date 是最简单、最快的方法。

    每天返回一行(对于任何行的天数)。如果有平局,则选择任意行,除非您添加更多 ORDER BY 项目作为决胜局。

    【讨论】:

    • 感谢 Erwin,我还找到了另一个解决方案,我将其作为另一个答案发布,您认为它有什么缺点吗?
    【解决方案2】:

    我找到了一个相当易读的解决方案(即使它是一个带有子查询的查询,它可能比建议的解决方案效率低):

    SELECT * FROM MyTable WHERE SomeDateTime IN (
        SELECT MAX(SomeDateTime) FROM MyTable GROUP BY (SomeDateTime::date)
    )
    

    【讨论】:

    • 如果SomeDateTime 不是唯一的,则存在差异。虽然这个返回与每天最大时间戳匹配的 all 行,但我的解决方案每天最多返回 one 行。与row_number() vs. rank() 的区别相同。这取决于你到底需要什么。要查看哪个更快,只需使用 EXPLAIN ANALYZE 进行测试。
    猜你喜欢
    • 2012-10-26
    • 2017-01-22
    • 1970-01-01
    • 2013-06-28
    • 2020-05-26
    • 1970-01-01
    • 2019-02-18
    • 2020-10-01
    • 1970-01-01
    相关资源
    最近更新 更多