2010-04-21 6 views

Répondre

497
SELECT t1.name 
FROM table1 t1 
LEFT JOIN table2 t2 ON t2.name = t1.name 
WHERE t2.name IS NULL 

Q: Qu'est-ce qui se passe ici?

A: Conceptuellement, nous sélectionnons toutes les lignes de table1 et pour chaque ligne nous essayons de trouver une ligne table2 avec la même valeur pour la colonne name. S'il n'y a pas une telle ligne, nous laissons la partie table2 de notre résultat vide pour cette ligne. Ensuite, nous limitons notre sélection en sélectionnant uniquement les lignes du résultat où la ligne correspondante n'existe pas. Enfin, nous ignorons tous les champs de notre résultat à l'exception de la colonne name (celle dont nous sommes sûrs, de table1).

Bien qu'il ne peut pas être la méthode la plus performante possible dans tous les cas, il devrait fonctionner dans pratiquement tous les moteurs de base de données jamais que les tentatives de mettre en œuvre ANSI 92 SQL

+14

@ z-boss: C'est aussi le moins performant sur SQL Server: http://explainextended.com/2009/09/15/not-in-vs-not-exists-vs-left-join-is-null-sql -server/ –

+0

Merci, fonctionne bien avec de grands ensembles de données – sirus

+0

@Kris pouvez-vous s'il vous plaît décrire ce qui se passe ici? –

158
SELECT name 
FROM table2 
WHERE name NOT IN 
    (SELECT name 
    FROM table1) 

ou

SELECT name 
FROM table2 
WHERE NOT EXISTS 
    (SELECT * 
    FROM table2 
    WHERE table1.name = table2.name) 

Voir this question pour 3 techniques pour accomplir ceci

+4

La syntaxe "not in" fonctionne également dans SQLite. – jftuga

+14

Ceci est incroyablement lent avec de grandes quantités de données. – Lightbulb1

+0

Ouais, en effet il est très lent – sirus

25

Ceci est la théorie pure d'ensemble que vous pouvez réaliser avec le minus o peration.

select id, name from table1 
minus 
select id, name from table2 
+0

Pensez-vous que c'est beaucoup plus efficace que la gauche? – uhs

+0

Il devrait être. La commande moins est conçue pour cette situation exacte. Bien sûr, la seule façon de juger un ensemble de données particulier est de l'essayer dans les deux sens et de voir ce qui fonctionne le plus rapidement. – Winter

+5

Dans T-SQL, l'opérateur set est "sauf". Ceci est très pratique pour moi et n'a pas causé de ralentissement. –

53

Je n'ai pas suffisamment de points de rep pour voter la 2ème réponse. Mais je suis en désaccord avec les commentaires sur la première réponse. La deuxième réponse:

SELECT name 
FROM table2 
WHERE name NOT IN 
    (SELECT name 
    FROM table1) 

FAR est plus efficace en pratique. Je ne sais pas pourquoi, mais je le cours contre des records 800k + et la différence est énorme avec l'avantage donné à la 2ème réponse affichée ci-dessus. Juste mes 0,02 $

+17

Dans la requête NOT IN la sous-requête est exécutée une seule fois, dans la requête EXISTS la sous-requête est effectuée pour chaque ligne – Carrick

+0

vous êtes génial :) de cette façon, je convertis ma requête 25 sec en utilisant left join à 0 sec. –

13

Méfiez-vous des pièges. Si le champ Name dans Table1 contient des valeurs nulles, vous êtes surpris. Mieux vaut:

SELECT name 
FROM table2 
WHERE name NOT IN 
    (SELECT ISNULL(name ,'') 
    FROM table1) 
+0

COALESCE> ISNULL (ISNULL est une addition T-SQL inutile au langage qui ne fait rien de nouveau ou de mieux que COALESCE) – Kris

4

Ce travail pointu pour moi

SELECT * 
FROM [dbo].[table1] t1 
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID] 
WHERE t2.[t2_ID] IS NULL 
6

Voici ce qui a fonctionné le mieux pour moi.

SELECT * 
FROM @T1 
EXCEPT 
SELECT a.* 
FROM @T1 a 
JOIN @T2 b ON a.ID = b.ID 

Cela a été plus de deux fois plus rapide que toute autre méthode que j'ai essayé.

Questions connexes