AVERTISSEMENT CONCERNANT LES SOLUTIONS:
DE NOMBREUSES SOLUTIONS EXISTANTES DONNERONT UNE FAUTE SORTIE SI LES RANGÉES NE SONT PAS UNIQUES
Si vous êtes la seule personne à créer des tables, cela peut ne pas être pertinent, mais plusieurs solutions donneront un nombre de lignes de sortie différent du code en question, lorsque l'une des tables peut ne pas contenir de lignes uniques.
AVERTISSEMENT CONCERNANT L'ÉNONCÉ DU PROBLÈME:
IN AVEC PLUSIEURS COLONNES N'EXISTE PAS, PENSEZ ATTENTIVEMENT CE QUE VOUS VOULEZ
Quand je vois un in avec deux colonnes, je peux l'imaginer pour signifier deux choses:
- La valeur de la colonne a et de la colonne b apparaît dans l'autre tableau indépendamment
- Les valeurs de la colonne a et de la colonne b apparaissent dans l'autre tableau ensemble sur la même ligne
Le scénario 1 est assez trivial, utilisez simplement deux instructions IN.
Conformément à la plupart des réponses existantes, je donne ici un aperçu des approches mentionnées et supplémentaires pour le scénario 2 (et un bref jugement):
EXISTS (sûr, recommandé pour SQL Server)
Tel que fourni par @mrdenny, EXISTS sonne exactement comme ce que vous recherchez, voici son exemple:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
LEFT SEMI JOIN (Safe, recommandé pour les dialectes qui le supportent)
C'est une manière très concise de rejoindre, mais malheureusement, la plupart des dialectes SQL, y compris le serveur SQL, ne le prennent pas actuellement en charge.
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
Plusieurs instructions IN (sûr, mais attention à la duplication de code)
Comme mentionné par @cataclysm, l'utilisation de deux instructions IN peut également faire l'affaire, peut-être même qu'elle surpassera les autres solutions. Cependant, vous devez faire très attention à la duplication de code. Si vous souhaitez effectuer une sélection dans une autre table ou modifier l'instruction where, vous risquez davantage de créer des incohérences dans votre logique.
Solution basique
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
Solution sans duplication de code (je pense que cela ne fonctionne pas dans les requêtes SQL Server régulières)
WITH mytmp AS (SELECT a, b FROM T2 WHERE something);
SELECT * from T1
WHERE a IN (SELECT a FROM mytmp)
AND b IN (SELECT b FROM mytmp)
INNER JOIN (techniquement, cela peut être sécurisé, mais souvent cela n'est pas fait)
La raison pour laquelle je ne recommande pas d'utiliser une jointure interne comme filtre, c'est qu'en pratique, les gens laissent souvent les doublons dans la table de droite provoquer des doublons dans la table de gauche. Et puis, pour aggraver les choses, ils rendent parfois le résultat final distinct alors que la table de gauche n'a peut-être pas besoin d'être unique (ou pas unique dans les colonnes que vous sélectionnez). De plus, cela vous donne la possibilité de sélectionner une colonne qui n'existe pas dans le tableau de gauche.
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
Erreurs les plus courantes:
- Rejoindre directement sur T2, sans sous-requête sûre. Entraînant un risque de duplication)
- SELECT * (garanti pour obtenir les colonnes de T2)
- SELECT c (ne garantit pas que votre colonne vient et proviendra toujours de T1)
- Pas de DISTINCT ou DISTINCT au mauvais endroit
CONCATENATION DE COLONNES AVEC SEPARATEUR (Pas très sûr, performances horribles)
Le problème fonctionnel est que si vous utilisez un séparateur qui pourrait apparaître dans une colonne, il devient difficile de s'assurer que le résultat est précis à 100%. Le problème technique est que cette méthode entraîne souvent des conversions de type et ignore complètement les index, ce qui entraîne des performances potentiellement horribles. Malgré ces problèmes, je dois admettre que je l'utilise encore parfois pour des requêtes ad hoc sur de petits ensembles de données.
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
Notez que si vos colonnes sont numériques, certains dialectes SQL vous demanderont d'abord de les convertir en chaînes. Je crois que le serveur SQL le fera automatiquement.
Pour résumer les choses: comme d'habitude, il existe de nombreuses façons de faire cela en SQL, utiliser des choix sûrs évitera les surprises et vous fera gagner du temps et de la tête à long terme.