根据PostgreSQL中的条件在组中选择一行

时间:2019-05-31 12:31:32

标签: sql postgresql group-by

我有一个这样的表(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解决方案。

1 个答案:

答案 0 :(得分:2)

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

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

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