Образовано предположение (при липса на повече информация):
NOT IN (...)
връща NULL
ако има NULL
са включени стойности и тестваната стойност не е в списъка. Но само TRUE
се квалифицира в WHERE
клауза.
a NOT IN (b,c)
се трансформира в:
a <> ALL ('{b,c}'::sometype[])
еквивалентно на:
(a <> b AND a <> c )
Ако викакви от тези стойности (от двете страни на оператора) е NULL
, получавате:
(NULL AND FALSE)
Това е:
NULL
И NULL
е еквивалентен на FALSE
в WHERE
клауза. Само TRUE
отговаря на изискванията.
Известно е, че това предизвиква недоверие у потребители, които не са запознати с тризначната логика.
Използвайте IS DISTINCT FROM
или NOT EXISTS
вместо. Или LEFT JOIN / IS NULL
.
Пример (повече предположения)
В този конкретен случай не се нуждаете от инкриминирания израз изобщо
SELECT ta.task_id AS id
, u.employee_id
, ta.task_status_type_id
FROM task_assignments ta
JOIN users u ON u.id = ta.user_id
WHERE ta.id IN (
SELECT max(ta.id) AS id
FROM task_details td
JOIN task_assignments ta USING (task_id)
WHERE td.developer_employee_id IS NULL
AND ta.task_type_id IN (6,7)
-- AND ta.task_status_type_id IS DISTINCT FROM 10 -- just cruft
AND ta.task_status_type_id = 9 -- this expression covers it
GROUP BY ta.task_id
)
Ако тайно използвате списък със стойности, които трябва да бъдат изключени, които биха могли да споделят елементи със списъка за включване:
...
AND (ta.task_status_type_id IN ( ... )) IS NOT TRUE
...
Или премахвате NULL стойности.
Или избягвате общи елементи в списъка за включване и изключване.