Postgres:如何在 Have 子句中进行 NULL 友好的 MIN 过滤以准确选择一行?
Posted
技术标签:
【中文标题】Postgres:如何在 Have 子句中进行 NULL 友好的 MIN 过滤以准确选择一行?【英文标题】:Postgres: How to make NULL friendly MIN filtering in Having clause to select exactly one row? 【发布时间】:2021-10-07 19:37:40 【问题描述】:根据 Gordon Linoff 的建议,我为 Postgres: How to make NULL friendly MIN filtering in Having clause? 创建了一个新的后续问题
SELECT userId FROM audit_table
GROUP BY userId
HAVING MIN(updatedDate) > ? OR MIN(updatedDate) IS NULL;
ORDER BY userId
LIMIT 1
有没有办法让这个查询在 POSTGRES 中更高效?
【问题讨论】:
您可以在帖子中添加索引和explain analyse
吗?
@Jim Jones 我有更新日期的索引
哪个索引?请添加查询计划。
将OR
转换为UNION
;按更新日期索引;限制每个子查询并限制 UNION。
您有单独的用户表吗? audit_table
有多大?有哪些索引可用?
【参考方案1】:
如果您担心性能,您可以:
将 OR 转换为 UNION ALL。 索引updatedDate
。
限制每个子查询,并且
限制 UNION ALL。
例如你可以添加索引(和一些数据):
create table audit_table (
userId int,
updatedDate date
);
insert into audit_table (userId, updatedDate) values
(123, '2021-02-03'),
(456, '2021-04-12'),
(789, '2021-01-22'),
(477, null);
create index ix1 on audit_table (updatedDate nulls last, userId);
那么查询将使用索引:
select *
from (
(
select userId, updatedDate
from audit_table
order by updatedDate nulls last
limit 1
)
union all
(
select userId, updatedDate
from audit_table
where updatedDate is null
limit 1
)
) x
order by updatedDate nulls last
limit 1
结果:
userid updateddate
------- -----------
789 2021-01-22
当有大量行时,上面的查询将使用索引。如果表只有几百行,引擎可能最终会忽略索引,而是读取整个表。
注意:如果同时找到空行和非空行,您可以选择优先考虑哪一行。在上一行到最后一行中,nulls first
将优先考虑空行,而nulls last
将优先考虑非空行。
请参阅DB Fiddle 的运行示例。
【讨论】:
以上是关于Postgres:如何在 Have 子句中进行 NULL 友好的 MIN 过滤以准确选择一行?的主要内容,如果未能解决你的问题,请参考以下文章
SQL - 如何在have子句中对结果进行分组和筛选后,如何汇总列?
如何在 Hive/SQL 的 where/have 子句中使用 min()(以避免子查询)