我想有效地检查一个表是否包含任何匹配 <condition A> 并且不匹配 <condition B> 的行,其中条件是任意的。
在 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)
问题是可怕的空值。假设 <condition A> 是name = 'Aaron'而 <condition B> 是age = 21。该查询将正确识别任何年龄不等于 21 的 Aarons,但它无法识别任何年龄为空的 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”子句的第一个查询是比第二个快得多 - 它可以在找到一个匹配的记录后立即停止,并且不必进行两次单独的扫描)。
我怎样才能有效地做到这一点,而不会对空值感到困惑?