【问题标题】:Select one row inside a group according to a criteria in PostgreSQL根据 PostgreSQL 中的条件选择组内的一行
【发布时间】:2019-05-31 12:31:31
【问题描述】:

我有一张这样的桌子 (tbl):

+----+-----+------+-----+
| pk | grp | attr | val |
+----+-----+------+-----+
|  0 |   0 | ohif |   4 |
|  1 |   0 | foha |  56 |
|  2 |   0 | slns |   2 |
|  3 |   1 | faso |  11 |
|  4 |   1 | tepj |   4 |
|  5 |   2 | bnda |  12 |
|  6 |   2 | ojdf |   9 |
|  7 |   2 | anaw |   1 |
+----+-----+------+-----+

我想从每个组中选择一行,特别是每个组的最大 val

我可以轻松选择grpval

SELECT grp, MAX(val)
FROM tbl
GROUP BY grp

让出这张桌子(tbl2):

+-----+-----+
| grp | val |
+-----+-----+
|   0 |  56 |
|   1 |  11 |
|   2 |  12 |
+-----+-----+

但是,我想要这张桌子:

+----+-----+------+-----+
| pk | grp | attr | val |
+----+-----+------+-----+
|  1 |   0 | foha |  56 |
|  3 |   1 | faso |  11 |
|  5 |   2 | bnda |  12 |
+----+-----+------+-----+

由于(grp, val) 构成密钥,我可以将tbl2tbl 左连接到同一grpval

但是,我想知道是否有任何其他解决方案:在我的实际情况下,tbl 是一个非常复杂且繁重的派生表,并且我有无法使用临时表的设计约束。有什么办法可以按照val对每组内的行进行排序,然后为每组取第一条记录?

我使用的是 PostgreSQL 10,但标准 SQL 解决方案是最好的。

【问题讨论】:

    标签: sql postgresql group-by


    【解决方案1】:

    在 Postgres 中,最好的方法是 distinct on:

    SELECT DISTINCT ON (t.grp) t.*
    FROM tbl
    ORDER BY grp, val DESC;
    

    特别是,这可以利用(grp, val desc) 上的索引。

    【讨论】:

    • 整合:PosgreSQL 文档特别提到 "SELECT DISTINCT ON (表达式 [, ...] ) 仅保留给定表达式计算结果为相等的每组行的第一行。它们[...] 使用与 ORDER BY [...] 相同的规则进行解释。请注意,每个集合的“第一行”是不可预测的,除非使用 ORDER BY 来确保所需的行首先出现。”我>。这使您的DISTINCT ON 解决方案正确。应该注意的是,对于DISTINCT 子句,不会对排序做出相同的保证!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2015-06-04
    • 2016-09-16
    • 2021-12-21
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多