Използвайте EXISTS израз:
WHERE NOT EXISTS (
SELECT FROM votes v -- SELECT list can be empty
WHERE v.some_id = base_table.some_id
AND v.user_id = ?
)
Разликата
... между NOT EXISTS() (Ⓔ) и NOT IN() (Ⓘ) е двойно:
-
Ефективност
Ⓔ обикновено е по-бързо. Той спира да обработва подзаявката веднага щом бъде намерено първото съвпадение. Ръководството:
Подзаявката обикновено ще се изпълнява достатъчно дълго, за да се определи дали поне един ред е върнат, а не чак до завършване.
Ⓘ също може да бъде оптимизиран от планировчика на заявки, но в по-малка степен, тъй като
NULLманипулирането го прави по-сложно. -
Коректност
Ако една от получените стойности в израза на подзаявката е
NULL, резултатът от Ⓘ еNULL, докато общата логика очакваTRUE- и Ⓔ ще върнатTRUE. Ръководството:Ако всички резултати на ред са или неравни, или нулеви, с поне една нула, тогава резултатът от
NOT INе нула.
По същество (NOT) EXISTS е по-добрият избор в повечето случаи.
Пример
Вашата заявка може да изглежда така:
SELECT *
FROM questions q
WHERE NOT EXISTS (
SELECT FROM votes v
WHERE v.question_id = q.id
AND v.user_id = ?
);
Не присъединете се към votes в основната заявка. Това ще анулира усилията.
Освен това NOT EXISTS и NOT IN има допълнителни опции за синтаксис с LEFT JOIN / IS NULL и EXCEPT . Вижте:
- Изберете редове, които не присъстват в друга таблица