Een weloverwogen gok (bij gebrek aan meer informatie):
NOT IN (...)
retourneert NULL
indien aanwezig NULL
waarden zijn betrokken en de geteste waarde staat niet in de lijst. Maar alleen TRUE
kwalificeert zich in een WHERE
clausule.
a NOT IN (b,c)
wordt getransformeerd naar:
a <> ALL ('{b,c}'::sometype[])
gelijk aan:
(a <> b AND a <> c )
Indien enige van deze waarden (aan weerszijden van de operator) is NULL
, krijg je:
(NULL AND FALSE)
Dat is:
NULL
En NULL
is gelijk aan FALSE
in een WHERE
clausule. Alleen TRUE
komt in aanmerking.
Het is bekend dat dit ongeloof veroorzaakt bij gebruikers die niet bekend zijn met driewaardige logica.
Gebruik IS DISTINCT FROM
of NOT EXISTS
in plaats van. Of LEFT JOIN / IS NULL
.
Voorbeeld (meer giswerk)
In dit specifieke geval heb je de belaste uitdrukking helemaal niet nodig
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
)
Als u in het geheim een lijst met uit te sluiten waarden gebruikt die elementen zouden kunnen delen met de opnamelijst:
...
AND (ta.task_status_type_id IN ( ... )) IS NOT TRUE
...
Of u verwijdert NULL-waarden.
Of u vermijdt veelvoorkomende elementen in de opname- en uitsluitingslijst.