Przypuszczenie oparte na wiedzy (z braku więcej informacji):
NOT IN (...)
zwraca NULL
jeśli jakikolwiek NULL
wartości są zaangażowane, a testowanej wartości nie ma na liście. Ale tylko TRUE
kwalifikuje się w WHERE
klauzula.
a NOT IN (b,c)
przekształca się w:
a <> ALL ('{b,c}'::sometype[])
odpowiednik:
(a <> b AND a <> c )
Jeśli jakikolwiek z tych wartości (po obu stronach operatora) to NULL
, otrzymujesz:
(NULL AND FALSE)
To jest:
NULL
I NULL
jest odpowiednikiem FALSE
w WHERE
klauzula. Tylko TRUE
kwalifikuje się.
Wiadomo, że powoduje to niedowierzanie użytkownikom niezaznajomionym z logiką trójwartościową.
Użyj IS DISTINCT FROM
lub NOT EXISTS
zamiast. Lub LEFT JOIN / IS NULL
.
Przykład (więcej zgadywania)
W tym konkretnym przypadku nie potrzebujesz oskarżanego wyrażenia w ogóle
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
)
Jeśli potajemnie używasz listy wartości do wykluczenia, które mogą współdzielić elementy z listą włączenia:
...
AND (ta.task_status_type_id IN ( ... )) IS NOT TRUE
...
Lub wyeliminujesz wartości NULL.
Lub unikniesz wspólnych elementów na liście włączeń i wykluczeń.