在 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 NULL
列 b.z
,这也会对您不利,。外部联接可以为列引入 NULL
值。在这个简单的查询中不会有效,但在更复杂的查询中可能有效。
虽然像 min
、max
或 count
这样的聚合函数 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
我正在使用 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 NULL
列 b.z
,这也会对您不利,。外部联接可以为列引入 NULL
值。在这个简单的查询中不会有效,但在更复杂的查询中可能有效。
虽然像 min
、max
或 count
这样的聚合函数 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
(
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