在 postgresql 中通过 max(col) 获取行过滤

Get row filtering by max(col) in postgresql

我正在使用 postgresql,但我不熟悉它。这段代码有效,但我想知道我是否可以用更直接的方式编写它。这里我join bar是为了在子查询中加入bar。我希望有一些简单的东西,比如 select * from bar group by baz using max(z)

select *
from foo f
join bar b on(f.baz=b.baz AND b.z in (select max(z) from bar group by baz))
where uid1 = 120

只需使用distinct on:

select distinct on (f.baz) *
from foo f join
     bar b
     on f.baz = b.baz 
where uid1 = 120
order by f.baz, b.z desc;


您好,
您可以进行以下查询,

SELECT * FROM foo f
INNER JOIN (SELECT baz, MAX(z) FROM bar GROUP BY baz) b
ON (f.baz = b.baz)
WHERE f.uid1 = 120;

只需将 bar 与派生的 MAX(z) 连接起来并填充您需要的值。 uid1 必须来自 foo table 并且因为 f 用作别名,如果不是更改为 b.uid1

几乎但不完全正确。如果列可以是 NULL,则 max(b.z)ORDER BY b.z DESC 之间存在细微差别。经常被忽视并引起很多头痛。

即使定义了 NOT NULLb.z,这也会对您不利,。外部联接可以为列引入 NULL 值。在这个简单的查询中不会有效,但在更复杂的查询中可能有效。

虽然像 minmaxcount 这样的聚合函数 ignore NULL 值,当在 ORDER BY 子句中使用同一列时,那些 必须 以某种方式处理。
在默认排序顺序 NULL 中,值排序 最后 。当排序顺序与 DESC 颠倒时,NULL 值排序 first。必须这样才能保持一致。
因此,如果任何 NULL 值在对等集合中,您会从 DISTINCT ON 获得一行 baz IS NULL,您将从 [=] 获得最大的非空值(如果有) 12=]。很可能不是你想要的。您可以使用 NULLS LAST:

修复它
  • PostgreSQL sort by datetime asc, null first?

此外,在使用 SELECT * 时,您不希望 return 连接列 baz 两次 - 保证相同。 USING 子句派上用场,它只 return 列 一次

所以:

SELECT DISTINCT ON (baz) *
FROM   foo f
JOIN   bar b USING (baz)
WHERE  uid1 = 120   -- where from?
ORDER  BY baz, b.z DESC NULLS LAST;

NULLS LAST 不会造成伤害,即使没有 NULL 值 - 除非你真的希望 NULL 值占上风。

DISTINCT ON的详细解释:

  • Select first row in each GROUP BY group?

更快

由于 uid1 来自 baz (),此查询通常对于大 tables 更快:

SELECT *
FROM   foo f
JOIN  (
   SELECT DISTINCT ON (baz) *
   FROM   bar
   WHERE  uid1 = 120
   ORDER  BY baz, z DESC NULLS LAST
   ) b USING (baz);

根据 table 定义和数据分布,可能会有更快的查询技术:

  • Optimize GROUP BY query to retrieve latest record per user