Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

SQL NOT IN não está funcionando

SELECT foreignStockId
FROM   [Subset].[dbo].[Products]  

Provavelmente retorna um NULL .

Um NOT IN a consulta não retornará nenhuma linha se houver NULL s existe na lista de NOT IN valores. Você pode excluí-los explicitamente usando IS NOT NULL como abaixo.
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) 

Ou reescreva usando NOT EXISTS em vez de.
SELECT stock.idstock,
       stock.descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  NOT EXISTS (SELECT *
                   FROM   [Subset].[dbo].[Products] p
                   WHERE  p.foreignstockid = stock.idstock) 

Além de ter a semântica que deseja o plano de execução para NOT EXISTS é muitas vezes mais simples como visto aqui.

A razão para a diferença de comportamento está na lógica de três valores usada no SQL. Os predicados podem ser avaliados como True , False , ou Unknown .

Um WHERE cláusula deve ser avaliada como True para que a linha seja retornada, mas isso não é possível com NOT IN quando NULL está presente conforme explicado abaixo.

'A' NOT IN ('X','Y',NULL) é equivalente a 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)
  • 'A' <> 'X' =True
  • 'A' <> 'S' =True
  • 'A' <> NULL =Unknown

True AND True AND Unknown avalia como Unknown de acordo com as tabelas de verdade para três lógicas de valor.

Os links a seguir têm algumas discussões adicionais sobre o desempenho das várias opções.
  • Devo usar NOT IN , OUTER APPLY , LEFT OUTER JOIN , EXCEPT , ou NOT EXISTS ?
  • NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL :SQL Server
  • Left outer join vs NOT EXISTS
  • NOT EXISTS vs NOT IN