Използвайте 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
. Вижте:
- Изберете редове, които не присъстват в друга таблица