95 votes

SQL NOT IN ne fonctionne pas

J'ai deux bases de données, une qui contient l'inventaire, et une autre qui contient un sous-ensemble des enregistrements de la base de données primaire.

L'instruction SQL suivante ne fonctionne pas :

SELECT  stock.IdStock
        ,stock.Descr       
FROM    [Inventory].[dbo].[Stock] stock
WHERE   stock.IdStock NOT IN
        (SELECT foreignStockId FROM
         [Subset].[dbo].[Products])

Le PAS dans ne fonctionne pas. La suppression du NOT donne les bons résultats, c'est-à-dire les produits qui se trouvent dans les deux bases de données. Cependant, l'utilisation du NOT IN ne renvoie AUCUN résultat.

Qu'est-ce que je fais mal, des idées ?

0 votes

Êtes-vous sûr d'avoir des stock.IdStock qui ne sont pas du tout dans foreignStockId ?

0 votes

Avez-vous vraiment des articles dans Inventory qui n'est pas dans Subset ?

1 votes

Expliquez ce que la requête doit retourner. Actuellement, elle renvoie tous les articles en stock pour lesquels il n'y a pas de produit dans le sous-ensemble qui y fait référence.

252voto

Martin Smith Points 174101
SELECT foreignStockId
FROM   [Subset].[dbo].[Products]  

Il renvoie probablement un NULL .

A NOT IN La requête ne renverra pas de lignes si un élément de la liste est présent. NULL 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éécrire 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 voulez que le plan d'exécution de NOT EXISTS est souvent plus simple comme indiqué ici .

La raison de cette différence de comportement est due au fait que logique à trois valeurs utilisés en SQL. Les prédicats peuvent être évalués à True , False ou Unknown .

A WHERE doit être évaluée à True pour que la ligne soit retournée, mais cela 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' <> 'Y' = True
  • 'A' <> NULL = Unknown

True AND True AND Unknown évalue à Unknown par le tables de vérité pour la logique à trois valeurs .

Les liens suivants proposent des discussions supplémentaires sur les performances des différentes options.

0 votes

Cela a réglé le problème pour moi. Select * From x Where x.y not in( Select Distinct ISNULL(c,0))

1 votes

Oh mon dieu, en effet select retournait null et NOT IN ne fonctionnait pas correctement. 6 ans plus tard, je vous salue

4voto

MPękalski Points 1122

Si PAS DANS ne fonctionne pas, vous pouvez toujours essayer de faire JOINT GAUCHE . Puis filtrez par en utilisant une des valeurs de la table jointe, qui sont NULL . A condition que, la valeur que vous rejoignez par ne contient pas tout NULL valeur.

2voto

jitbit Points 8072

J'ajoute mes deux cents :

J'ai vu SQL Server renvoyer des résultats erronés même en passant à not exists y left join - dans les bases de données corrompues . Exécutez DBCC CHECKTABLE sur les tables concernées, regardez également le fichier NOT IN plan d'exécution de la requête et reconstruire les index concernés, cela devrait aider.

0voto

Raj Kamal Points 569

Vous pouvez également utiliser la clause Case pour aborder ces questions.

SELECT  stock.IdStock
        ,stock.Descr        
FROM    [Inventory].[dbo].[Stock] stock
WHERE   (Case when stock.IdStock IN
        (SELECT foreignStockId FROM
        [Subset].[dbo].[Products]) then 1 else 0 end) = 0 

cette syntaxe fonctionne dans SQL Server, Oracle et postgres

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X