2010-06-25 9 views
6

Ecco cosa sto cercando di realizzare:Query SQL per trovare righe che non sono presenti in altre tabelle

Ho due tabelle, chiamale prima e seconda. Ognuno di loro ha una colonna ID. Potrebbero avere altre colonne ma quelle non sono importanti. Ho un terzo tavolo, chiamalo terzo. Contiene due colonne, ID e ALTRO. ALTRE voci di riferimenti che potrebbero o meno essere presenti nelle tabelle prima e seconda.

Voglio interrogare terzo e cercare le righe che non hanno un valore di colonna OTHERID che si trova in entrambe le tabelle prima o seconda. L'obiettivo è eliminare quelle righe dalla terza tabella.

Esempio:

prima tabella:

ID 
1 
2 
3 

seconda tabella:

ID 
6 
7 
8 

terza tabella

ID | OTHERID 
21  1 
22  2 
23  3 
24  4 
25  5 
26  6 
27  7 
28  8 

In questo caso, avrei voluto recuperare il ID di terzi che non hanno ve un ID corrispondente in una tabella prima o seconda nella tabella. Mi aspetto di tornare i seguenti ID:

24 
25 

Quello che ho provato:

che ho fatto qualcosa di questo per ottenere indietro le voci in terza che non sono in prima:

select t.* from third t where not exists (select * from first f where t.otherid = f.id); 

e questo farmi tornare le seguenti righe:

ID | OTHERID 
24  4 
25  5 
26  6 
27  7 
28  8 

Allo stesso modo, posso ottenere quelli che non sono in secondo:

select t.* from third t where not exists (select * from second s where t.otherid = s.id); 

e vado a prendere:

ID | OTHERID 
21  1 
22  2 
23  3 
24  4 
25  5 

Quello che non posso ottenere il mio cervello circa questa mattina è come combinare le due query insieme per ottenere l'intersezione tra i due risultati set , così vengono restituite solo le righe con ID 24 e 25. Quelli sarebbero due file che potrei rimuovere da quando sono orfani.

Come lo risolveresti? Penso di essere sulla strada giusta, ma a questo punto sto semplicemente girando senza fare progressi.

risposta

14

Forse questo:

SELECT third.* 
FROM third 
LEFT JOIN first ON third.otherID = first.id 
LEFT JOIN second ON third.otherID = second.id 
WHERE first.id IS NULL AND second.id IS NULL 
+0

Grazie! Un altro modo per risolverlo. – itsmatt

+0

@itsmatt: dovresti davvero considerare l'utilizzo di questo per prestazioni migliori. L'ottimizzatore di MySQL5 è piuttosto zoppo quando si tratta di sottocommissioni dipendenti. –

7

Basta usare

select t.* 
from third t 
where 
     not exists (select * from first f where t.otherid = f.id) 
    and not exists (select * from second s where t.otherid = s.id) 
+0

@Lieven: Grazie. –

+0

Grande, grazie! Frustrante che ero vicino e non potevo mettere insieme 2 e 2 su questo. Chalk it to a late Thursday :) – itsmatt

+2

Utilizzare LEFT OUTER JOIN come suggerito da Serty Oan sarebbe molto più efficiente. Le sottoquery dipendenti come quelle utilizzate nelle clausole 'not exist' dovranno essere eseguite una volta per riga mentre una query LEFT OUTER JOIN dovrà solo scansionarla una volta. (MySQL 5.x) –

4
SELECT t.ID 
FROM third t 
WHERE t.OTHERID NOT IN (
    SELECT ID 
    FROM first 

    UNION 

    SELECT ID 
    FROM second 
) 
+1

+1. Questo è come lo scriverei, ma "non esiste" dovrebbe funzionare meglio. (+1 su quello a btw :) –

+0

oh grazie. Non sapevo che NON ESISTE ha funzionato meglio. – SAGExSDX

+0

Grazie! Anche questo ha funzionato. – itsmatt

Problemi correlati