ATTENZIONE SULLE SOLUZIONI:
MOLTE SOLUZIONI ESISTENTI DANNO L'USCITA SBAGLIATA SE LE FILE NON SONO UNICHE
Se sei l'unica persona che crea tabelle, questo potrebbe non essere pertinente, ma diverse soluzioni forniranno un numero diverso di righe di output rispetto al codice in questione, quando una delle tabelle potrebbe non contenere righe univoche.
AVVERTENZA SULLA DICHIARAZIONE DEL PROBLEMA:
IN CON PIÙ COLONNE NON ESISTE, PENSA CON ATTENZIONE A COSA VUOI
Quando vedo un in con due colonne, posso immaginare che significhi due cose:
- Il valore della colonna a e della colonna b viene visualizzato nell'altra tabella in modo indipendente
- I valori della colonna a e della colonna b compaiono insieme nell'altra tabella sulla stessa riga
Lo scenario 1 è abbastanza banale, basta usare due istruzioni IN.
In linea con la maggior parte delle risposte esistenti, fornisco una panoramica degli approcci citati e aggiuntivi per lo Scenario 2 (e un breve giudizio):
EXISTS (sicuro, consigliato per SQL Server)
Come fornito da @mrdenny, EXISTS suona esattamente come quello che stai cercando, ecco il suo esempio:
SELECT * FROM T1
WHERE EXISTS
(SELECT * FROM T2
WHERE T1.a=T2.a and T1.b=T2.b)
LEFT SEMI JOIN (Sicuro, consigliato per i dialetti che lo supportano)
Questo è un modo molto conciso per unirsi, ma sfortunatamente la maggior parte dei dialetti SQL, incluso SQL Server, al momento non lo supporta.
SELECT * FROM T1
LEFT SEMI JOIN T2 ON T1.a=T2.a and T1.b=T2.b
Istruzioni multiple IN (sicure, ma attenzione alla duplicazione del codice)
Come accennato da @cataclysm, usare due istruzioni IN può fare anche il trucco, forse supererà anche le altre soluzioni. Tuttavia, ciò di cui dovresti fare molta attenzione è la duplicazione del codice. Se mai si desidera selezionare da una tabella diversa o modificare l'istruzione where, è un rischio maggiore che si creino incoerenze nella logica.
Soluzione di base
SELECT * from T1
WHERE a IN (SELECT a FROM T2 WHERE something)
AND b IN (SELECT b FROM T2 WHERE something)
Soluzione senza duplicazione del codice (credo che questo non funzioni nelle normali query di SQL Server)
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 (tecnicamente può essere reso sicuro, ma spesso non lo si fa)
Il motivo per cui non consiglio di usare un join interno come filtro, è perché in pratica le persone spesso lasciano duplicati nella tabella di destra causando duplicati nella tabella di sinistra. E poi, a peggiorare le cose, a volte rendono distinto il risultato finale mentre la tabella di sinistra potrebbe non aver bisogno di essere unica (o non unica nelle colonne selezionate). Inoltre ti dà la possibilità di selezionare effettivamente una colonna che non esiste nella tabella di sinistra.
SELECT T1.* FROM T1
INNER JOIN
(SELECT DISTINCT a, b FROM T2) AS T2sub
ON T1.a=T2sub.a AND T1.b=T2sub.b
Errori più comuni:
- Partecipare direttamente su T2, senza una subquery sicura. Con conseguente rischio di duplicazione)
- SELEZIONA * (Garantito per ottenere colonne da T2)
- SELEZIONA c (Non garantisce che la tua colonna arrivi e provenga sempre da T1)
- Nessun DISTINCT o DISTINCT nel posto sbagliato
CONCATENAZIONE DI COLONNE CON SEPARATORE (Prestazioni non molto sicure, orribili)
Il problema funzionale è che se si utilizza un separatore che potrebbe verificarsi in una colonna, diventa difficile garantire che il risultato sia accurato al 100%. Il problema tecnico è che questo metodo spesso comporta conversioni di tipo e ignora completamente gli indici, con conseguenti prestazioni orribili. Nonostante questi problemi, devo ammettere che a volte lo uso ancora per query ad hoc su piccoli set di dati.
SELECT * FROM T1
WHERE CONCAT(a,"_",b) IN
(SELECT CONCAT(a,"_",b) FROM T2)
Nota che se le tue colonne sono numeriche, alcuni dialetti SQL richiederanno di lanciarle prima nelle stringhe. Credo che SQL Server lo farà automaticamente.
Per concludere: come al solito ci sono molti modi per farlo in SQL, l'uso di scelte sicure eviterà sorprese e ti farà risparmiare tempo e titoli a lungo termine.