Я хочу эффективно проверить, содержит ли таблица какие-либо строки, которые соответствуют <условие A> и не соответствуют <условие 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)
Проблема в страшных нулевых значениях. Допустим, <условие A> равно имя = 'Аарон' , а <условие B> равно возраст = 21 . Запрос правильно идентифицирует любого Аарона, чей возраст не равен 21, но он не может идентифицировать любого Аарона, чей возраст равен нулю.
Вот правильное решение, но для таблицы с миллионами записей это может занять некоторое время:
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...)
К сожалению, эти два условия будут произвольными, сложными, изменяющимися и, как правило, вне моего контроля. Они генерируются из среды персистентности приложения из поисковых запросов пользователей, и хотя мы пытаемся поддерживать наши индексы на уровне наших пользователей, большую часть времени они будут вызывать сканирование больших таблиц (именно поэтому этот первый запрос с предложением «exist» намного быстрее, чем вторая - она может остановиться, как только найдет одну подходящую запись, и ей не нужно делать два отдельных сканирования).
Как я могу сделать это эффективно, не затирая нули?