Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

SQL NOT IN ne fonctionne pas

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

Renvoie probablement un NULL .

Un NOT IN la requête ne renverra aucune ligne s'il y en a NULL s existe dans la liste des NOT IN valeurs. Vous pouvez les exclure explicitement en utilisant IS NOT NULL comme ci-dessous.

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 réécrivez en utilisant NOT EXISTS à la place.

SELECT stock.idstock,
       stock.descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  NOT EXISTS (SELECT *
                   FROM   [Subset].[dbo].[Products] p
                   WHERE  p.foreignstockid = stock.idstock) 

En plus d'avoir la sémantique que vous souhaitez, le plan d'exécution pour NOT EXISTS est souvent plus simple comme on le voit ici.

La raison de la différence de comportement est due à la logique à trois valeurs utilisée dans SQL. Les prédicats peuvent être évalués à True , False , ou Unknown .

Un WHERE la clause doit être évaluée à True pour que la ligne soit retournée mais ce n'est pas possible avec NOT IN quand NULL est présent comme expliqué ci-dessous.

'A' NOT IN ('X','Y',NULL) est équivalent à 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

  • 'A' <> 'X' =True
  • 'A' <> 'O' =True
  • 'A' <> NULL =Unknown

True AND True AND Unknown est évalué à Unknown selon les tables de vérité pour la logique à trois valeurs.

Les liens suivants contiennent des informations supplémentaires sur les performances des différentes options.

  • Dois-je utiliser 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