SELECT foreignStockId
FROM [Subset].[dbo].[Products]
Probablemente devuelve un NULL .
UN NOT IN la consulta no devolverá ninguna fila si alguna NULL s existe en la lista de NOT IN valores. Puede excluirlos explícitamente usando IS NOT NULL como se muestra a continuación.
SELECT stock.IdStock,
stock.Descr
FROM [Inventory].[dbo].[Stock] stock
WHERE stock.IdStock NOT IN (SELECT foreignStockId
FROM [Subset].[dbo].[Products]
WHERE foreignStockId IS NOT NULL)
O reescribe usando NOT EXISTS en su lugar.
SELECT stock.idstock,
stock.descr
FROM [Inventory].[dbo].[Stock] stock
WHERE NOT EXISTS (SELECT *
FROM [Subset].[dbo].[Products] p
WHERE p.foreignstockid = stock.idstock)
Además de tener la semántica que desea, el plan de ejecución para NOT EXISTS a menudo es más simple como se ve aquí.
La razón de la diferencia en el comportamiento se debe a la lógica de tres valores utilizada en SQL. Los predicados pueden evaluarse como True , False o Unknown .
Un WHERE la cláusula debe evaluarse como True para que se devuelva la fila, pero esto no es posible con NOT IN cuando NULL está presente como se explica a continuación.
'A' NOT IN ('X','Y',NULL) es equivalente a 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)
- 'A' <> 'X' =
True - 'A' <> 'Y' =
True - 'A' <> NULL =
Unknown
True AND True AND Unknown se evalúa como Unknown según las tablas de verdad para la lógica de tres valores.
Los siguientes enlaces tienen una discusión adicional sobre el rendimiento de las diversas opciones.
- ¿Debería usar
NOT IN? ,OUTER APPLY,LEFT OUTER JOIN,EXCEPT, oNOT EXISTS? NOT INfrente aNOT EXISTSfrente aLEFT JOIN / IS NULL:Servidor SQLLeft outer joinvsNOT EXISTSNOT EXISTSvsNOT IN