sql – 否定任意where子句条件(包括null测试)

我想有效地检查一个表是否包含任何匹配 的行.并且不匹配 ,其中条件是任意的.

在Oracle中,这几乎可以工作:

select count(*) from dual
where exists (
  select * from people
  where (<condition A>)
  and not (<condition B>)
);
-- returns zero if all rows that match <condition A> also match <condition B>
-- (well, almost)

问题是可怕的空值.让我们说 是name =’Aaron’和 是年龄= 21.查询将正确识别年龄不等于21的任何Aarons,但无法识别年龄为null的任何Aarons.

这是一个正确的解决方案,但在包含数百万条记录的表上,可能需要一段时间:

select (
  select count(*) from people
  where (<condition A>)
) - (
  select count(*) from people
  where (<condition A>)
  and (<condition B>)
) from dual;
-- returns zero if all rows that match <condition A> also match <condition B>
-- (correct, but it is s l o w...)

不幸的是,这两个条件将是任意的,复杂的,变化的,并且通常是我无法控制的.它们是从用户搜索的应用程序的持久性框架生成的,当我们尝试使用我们的用户保持索引时,很多时候它们会导致大表扫描(这就是为什么带有“exists”子句的第一个查询是比第二个快得多 – 它一旦找到一个匹配的记录就可以停止,而且不必进行两次单独的扫描.

如何在不充分利用空值的情况下有效地完成这项工作?

最佳答案 如果您有id字段,请尝试:

从双重中选择计数(*)
存在的地方(
选择*来自人
哪里(cond a)
和zzz.id没有(从人们中选择id(cond b))
);

点赞