NOT IN in postgresql not working [closed]

2019-01-20 07:38发布

问题:

I am not getting the output as expected, because

 AND ta.task_status_type_id NOT IN ( 10 )

is not working in below query.

SELECT
    ta.task_id AS id,
    u.employee_id AS employee_id,
    ta.task_status_type_id
FROM
    task_assignments AS ta,
    users AS u
WHERE
    u.id = ta.user_id
    AND ta.id IN (
                   SELECT
                       max ( ta.id ) OVER ( partition BY ta.task_id ) AS id
                   FROM
                       task_details AS td,
                       task_assignments AS ta
                   WHERE
                       td.task_id = ta.task_id
                       AND td.developer_employee_id IS NULL
                       AND ta.task_type_id IN(6,7)
                       AND ta.task_status_type_id NOT IN ( 10 )
                       AND ta.task_status_type_id IN ( 9 )


    );

Please help in resolving the error.

回答1:

An educated guess (for lack of more information):

NOT IN (...) returns NULL if any NULL values are involved and the tested value is not in the list. But only TRUE qualifies in a WHERE clause.

a NOT IN (b,c)

is transformed to:

a <> ALL ('{b,c}'::sometype[])

equivalent to:

(a <> b AND a <> c )

If any of these values (on either side of the operator) is NULL, you get:

(NULL AND FALSE)

That's:

NULL

And NULL is equivalent to FALSE in a WHERE clause. Only TRUE qualifies.

This has been known to cause disbelieve in users unfamiliar with tri-valued logic.

Use IS DISTINCT FROM or NOT EXISTS instead. Or LEFT JOIN / IS NULL.

Example (more guesswork)

In this particular case, you don't need the incriminated expression at all

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
   )

If you are secretly using a list of values to be excluded that could share elements with the inclusion list:

... 
    AND    (ta.task_status_type_id IN ( ... )) IS NOT TRUE
...

Or you weed out NULL values.
Or you avoid common elements in inclusion and exclusion list.