如何将聚合函数添加到不在 select 中的非分组列

How to add aggregation function to non grouped column which is not in select

我有一个 table tab,其中包含列 a,b,c,d。但是以下查询将不起作用,因为 c 不在 group by 子句中或缩减函数中。

SELECT a, b, c FROM tab GROUP BY a, b;

但我想要的是selectc基于d的最大值。我如何在 PostgreSQL 中执行此查询?

| a | b | c | d   |
| 1 | 2 | 3 | 100 |
| 1 | 2 | 4 | 110 |
| 1 | 2 | 5 | 90  |

作为输出我需要第2行的结果,因为d中的值是最高的。

经典top-n-per-group。一种方法是使用 ROW_NUMBER:

WITH
CTE
AS
(
    SELECT
        a, b, c
        ,ROW_NUMBER() OVER(PARTITION BY a, b ORDER by d DESC) AS rn
    FROM tab
)
SELECT
    a, b, c
FROM CTE
WHERE rn = 1;

(a, b, d, c) 上的索引应该有所帮助。

当 table 每组只有几行并且服务器必须读取大部分 table 时,使用 ROW_NUMBER 的方法效果很好。例如,table 有 100 万行和 80 万个不同的 (a, b) 组。您必须以任何方式阅读大多数行。

如果 table 有 100 万行并且只有 20 个不同的 (a, b) 组,最好对适当的索引进行 20 次查找而不是读取所有行。

在 Postgres 中,您可以使用 distinct on:

SELECT DISTINCT ON (a, b) a, b, c
FROM tab
ORDER BY a, b, d DESC;

此语法特定于 Postgres。它通常是执行此类操作的最有效方法。

如果你有主键, 您可以 select 在子查询中使用 max d 并在主查询中内部加入该查询。