Un'ipotesi plausibile (per mancanza di ulteriori informazioni):
NOT IN (...)
restituisce NULL
se presente NULL
i valori sono coinvolti e il valore testato non è nell'elenco. Ma solo TRUE
si qualifica in un WHERE
clausola.
a NOT IN (b,c)
viene trasformato in:
a <> ALL ('{b,c}'::sometype[])
equivalente a:
(a <> b AND a <> c )
Se qualsiasi di questi valori (su entrambi i lati dell'operatore) è NULL
, ottieni:
(NULL AND FALSE)
Questo è:
NULL
E NULL
è equivalente a FALSE
in un WHERE
clausola. Solo TRUE
si qualifica.
Questo è noto per causare incredulità negli utenti che non hanno familiarità con la logica a tre valori.
Usa IS DISTINCT FROM
o NOT EXISTS
invece. Oppure LEFT JOIN / IS NULL
.
Esempio (più congetture)
In questo caso particolare, non hai bisogno dell'espressione incriminata per niente
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
)
Se stai utilizzando segretamente un elenco di valori da escludere che potrebbero condividere elementi con l'elenco di inclusione:
...
AND (ta.task_status_type_id IN ( ... )) IS NOT TRUE
...
Oppure elimini i valori NULL.
Oppure eviti gli elementi comuni nell'elenco di inclusione ed esclusione.