排除那些有任意非唯一匹配的唯一记录
我的数据看起来是这样的:
create table t(date,attribute)as values
('2026-01-03','A')
,('2026-01-03','A')
,('2026-01-03','B')
,('2026-01-04','A')
,('2026-01-04','A')
,('2026-01-05','C');
我需要过滤掉具有除A 以外其他属性的日期。也就是说,在我的示例中,我应该只看到 2026-01-04。
解决方案
select date
from t
group by date
having every(attribute is not distinct from 'A');
| 日期 |
|---|
| 2026-01-04 |
Every() 是一个符合SQL标准的名称,用于 bool_and() 的聚合函数。若 attribute 不是可为空的,你可以用 3VL 的 is not distinct from 来替换为普通的等值比较 =。
你也可以使用一个anti-join、其他 having 表达式,或一个 not exists:
select distinct date
from t as t1
where attribute='A'
and not exists(
select from t as t2
where t1.date=t2.date
and t2.attribute is not distinct from 'A');
以下来自对12万个随机样本的基准测试的执行时间:对12万个随机样本的基准测试:db<>fiddle的演示
| 变体 | 平均值 | 最小值 | 最大值 | 总和 | 标准差 | 众数 |
|---|---|---|---|---|---|---|
| every_indf(本回答) | 0.227862 | 0.220202 | 0.241795 | 2.278615 | 0.006628 | 0.220202 |
| min0_filter | 0.228749 | 0.222225 | 0.239936 | 2.28749 | 0.005546 | 0.222225 |
| zero_count_filter | 0.231584 | 0.224456 | 0.246823 | 2.315836 | 0.005983 | 0.224456 |
| not_exists | 0.250422 | 0.241111 | 0.259388 | 2.504223 | 0.005649 | 0.241111 |
| anti_join | 0.25294 | 0.246398 | 0.265615 | 2.529402 | 0.006184 | 0.246398 |
正如 [@MatBailie] 提示的那样,在具备正确的索引、规模和数据分布的前提下,not exists 和anti-joins可以并且会优于以seq-scan为重点的方法。示例:示例:
create index idx_a on t(date)with(fillfactor=100)where(attribute='A');
create index idx_idfa on t(date)with(fillfactor=100)where(attribute is distinct from 'A');
| 变体 | 平均值 | 最小值 | 最大值 | 总和 | 标准差 | 众数 |
|---|---|---|---|---|---|---|
| not_exists | 0.184743 | 0.174636 | 0.199075 | 1.847426 | 0.007394 | 0.174636 |
| anti_join | 0.191217 | 0.174656 | 0.265685 | 1.912169 | 0.026876 | 0.174656 |
| every_indf | 0.254697 | 0.235539 | 0.29734 | 2.546972 | 0.020578 | 0.235539 |
| min0_filter | 0.2656 | 0.245748 | 0.337827 | 2.655998 | 0.034727 | 0.245748 |
| zero_count_filter | 0.267132 | 0.241334 | 0.418356 | 2.671325 | 0.054409 | 0.241334 |
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。