sql >> Base de Datos >  >> RDS >> Sqlserver

SQL NO EN no funciona

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 , o NOT EXISTS ?
  • NOT IN frente a NOT EXISTS frente a LEFT JOIN / IS NULL :Servidor SQL
  • Left outer join vs NOT EXISTS
  • NOT EXISTS vs NOT IN