2010-06-25 7 views
6

Hier ist, was ich versuche zu erreichen:SQL-Abfrage Zeilen zu finden, die in anderen Tabellen nicht vorhanden sind

ich zwei Tabellen haben, nennen sie erste und zweite. Sie haben jeweils eine ID-Spalte. Sie können andere Spalten haben, aber diese sind nicht wichtig. Ich habe einen dritten Tisch, nenne ihn dritten. Es enthält zwei Spalten, ID und OTHERID. OTHERID verweist auf Einträge, die in der ersten und zweiten Tabelle vorhanden sein können.

Ich möchte dritten abfragen und nach Zeilen suchen, die keinen OTHERID-Spaltenwert haben, der in beiden Tabellen zuerst oder zweit gefunden wird. Das Ziel besteht darin, diese Zeilen aus der dritten Tabelle zu löschen.

Beispiel:

erste Tabelle:

ID 
1 
2 
3 

zweite Tabelle:

ID 
6 
7 
8 

dritte Tabelle

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

In diesem Fall würde ich will, dass die zum Abrufen IDs von Dritten, die nicht ha haben eine übereinstimmende ID entweder in der ersten Tabelle oder in der zweiten Tabelle. Ich würde erwarten, dass die folgenden IDs zurück zu bekommen:

24 
25 

Was ich habe versucht:

ich etwas getan habe dies die Einträge in Drittel zurück zu bekommen, die nicht in der ersten sind:

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

und das wird mir die folgenden Zeilen zurück:

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

in ähnlicher Weise kann ich diejenigen bekommen, die nicht in sind Zweitens:

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

und ich werde:

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

Was ich nicht mein Gehirn zu diesem Morgen bekommen kann, ist, wie die beiden Abfragen zu kombinieren zusammen, um den Schnittpunkt zwischen den beiden Ergebnissen Sätzen zu erhalten , so dass nur die Zeilen mit den IDs 24 und 25 zurückgegeben werden. Das wären zwei Zeilen, die ich entfernen könnte, weil sie Waisen sind.

Wie würden Sie das lösen? Ich denke, ich bin auf dem richtigen Weg, aber ich spinne nur an diesem Punkt und mache keine Fortschritte.

Antwort

14

Vielleicht dieses:

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

Danke! Eine andere Möglichkeit, es zu lösen. – itsmatt

+0

@itsmatt: Sie sollten wirklich in Betracht ziehen, dieses für bessere Leistung zu verwenden. Der MySQL5-Optimierer ist ziemlich lahm, wenn es um abhängige Unterabfragen geht. –

7

Verwenden Sie einfach

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: Danke. –

+0

Großartig, danke! Frustrierend, dass ich in der Nähe war und 2 und 2 nicht zusammen setzen konnte. Schreibe es bis zu einem späten Donnerstag :) – itsmatt

+2

Mit LINKE OUTER JOIN wie von Serty Oan vorgeschlagen wäre viel effizienter. Abhängige Unterabfragen, wie sie in den Klauseln "nicht vorhanden" verwendet werden, müssen einmal pro Zeile ausgeführt werden, während eine LINKE OUTER JOIN-Abfrage sie nur einmal abtasten müsste. (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. So würde ich es schreiben, aber die "nicht existiert" sollte besser funktionieren. (+1 auf dem einen zu btw :) –

+0

oh danke. Ich wusste nicht, dass NOT EXISTS besser lief. – SAGExSDX

+0

Danke! Das hat auch funktioniert. – itsmatt

Verwandte Themen