Comment avoir IN et NOT IN en même time

Quelqu'un peut-il m'aider à comprendre comment est la meilleure façon de faire cela?

J'ai une list de personnes avec des voitures. J'ai besoin d'exécuter une requête qui va returnner les gens qui ont un type de voiture et n'ont pas un autre type en même time.

Voici mon exemple:

ID Name CarType ----------- ---------- ---------- 1 John MINI VAN 1 John SUV 2 Mary SUV 2 Mary SEDAN 3 Paul SPORT 3 Paul TRUCK 4 Joe SUV 4 Joe MINI VAN 

Par exemple, je veux afficher uniquement les personnes qui ont SUV et ne pas avoir MINI VAN. Si nous essayons la clause CarType IN ('SUV') et NOT IN ('MINI VAN'), cela ne fonctionnera pas, parce que la deuxième déclaration est juste ignorée.

Pour renvoyer des personnes qui ont un type mais qui n'en ont pas un autre en même time, j'ai essayé ce qui suit:

  • Créez une table temporaire avec la clause IN, disons @Contains
  • Créez une table temporaire avec la clause NOT IN, disons @DoesNotContain
  • Rejoindre la table avec @Contains, cela fera la clause IN
  • Dans la clause where, searchz les ID qui ne se trouvent pas dans la table @DoesNotContain.

La requête que j'utilise est la suivante:

 --This is the IN Clause declare @Contains table( ID int not null ) --This is the NOT IN Clause declare @DoesNotContains table( ID int not null ) --Select IN insert into @Contains SELECT ID from @temp where CarType = 'SUV' --Select NOT IN insert into @DoesNotContains SELECT ID from @temp where CarType = 'MINI VAN' SELECT a.ID, Name FROM @temp a INNER JOIN @Contains b on b.ID = a.ID WHERE a.ID NOT IN (SELECT ID FROM @DoesNotContains) Group by a.ID, Name 

Cela rendra Mary parce qu'elle a un SUV mais n'a pas de MINI VAN.

Voici mes questions:

  • Est-il possible d'exécuter ce IN et NOT IN dans la requête, sans tables temporaires? Y a-t-il quelque chose de nouveau dans SQL qui fait ça? (Désolé, la dernière fois que j'ai travaillé avec SQL était SQL 2005)
  • Devrions-nous utiliser des tables temporaires pour cela?
  • Si c'est le path à parcourir, devrais-je utiliser IN et NOT IN au lieu de JOIN?
  • Comment replace la clause NOT IN par un JOIN?

Merci à tous!

MODIFIER

Je viens de tester les solutions mais malheureusement je n'ai pas précisé que j'avais besoin d'une combinaison de cartypes. Ma faute 🙁

Par exemple, si je veux tous les users qui ont SUV et MINI VAN mais pas TRUCK ET NON SEDAN. Dans ce cas, seul John est renvoyé.

Voici un moyen

 SELECT Id, Name FROM Cars WHERE CarType = 'SUV' EXCEPT SELECT Id, Name FROM Cars WHERE CarType = 'MINI VAN' 

Ou un autre

 SELECT Id, Name FROM Cars WHERE CarType IN ('SUV', 'MINI VAN') GROUP BY Id, Name HAVING MIN(CarType) = 'SUV' 

Ou une version plus générique qui répond aux différentes exigences du commentaire.

 SELECT Id, NAME FROM Cars WHERE CarType IN ( 'SUV', 'MINI VAN', 'TRUCK') GROUP BY Id, NAME HAVING COUNT(DISTINCT CASE WHEN CarType IN ( 'SUV', 'MINI VAN' ) THEN CarType END) = 2 AND COUNT(DISTINCT CASE WHEN CarType IN ( 'TRUCK' ) THEN CarType END) = 0 

Ceci est normalement accompli avec une seule requête en SQL standard, en utilisant NOT EXISTS :

 SELECT * FROM mytable AS t1 WHERE CarType = 'SUV' AND NOT EXISTS (SELECT * FROM mytable AS t2 WHERE t1.Name = t2.Name AND t2.CarType = 'MINI VAN') 

La requête ci-dessus sélectionnera toutes les personnes ayant CarType = 'SUV' , mais CarType = 'MINI VAN' pas CarType = 'MINI VAN' .

Utilisation de LEFT JOIN :

 SELECT a.ID, Name FROM @temp a INNER JOIN @Contains b ON b.ID = a.ID LEFT OUTER JOIN @DoesNotContains c ON c.ID = a.ID WHERE c.ID IS NULL 

INNER JOIN renverra les loggings où b.ID et a.ID correspondent.

Le LEFT OUTER JOIN returnne tous les loggings, avec NULL où il n'y a pas de correspondance – où WHERE c.ID IS NULL renvoie les loggings de qui ne correspondent pas à c .

Le mot-key except est votre ami. C'est l'idée générale

 where carType in (select carType from cars where you want to include them except select carType from cars where you want to exclude them) 

Vous pouvez travailler sur les détails.