排除那些有任意非唯一匹配的唯一记录

后端开发 2026-07-11

我的数据看起来是这样的:

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 不是可为空的,你可以用 3VLis 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章