MySQL: Wählen Sie Zeilen aus einer Tabelle aus, die sich nicht in einer anderen befinden


118

Wie wähle ich alle Zeilen in einer Tabelle aus, die in einer anderen nicht angezeigt werden?

Tabelle 1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Tabelle 2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Beispielausgabe für Zeilen in Tabelle1, die nicht in Tabelle2 enthalten sind:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Vielleicht sollte so etwas funktionieren:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)

Antworten:


96

Wenn Sie 300 Spalten haben, wie Sie in einem anderen Kommentar erwähnt haben, und alle Spalten vergleichen möchten (vorausgesetzt, die Spalten haben alle den gleichen Namen), können Sie mit a NATURAL LEFT JOINimplizit alle übereinstimmenden Spaltennamen zwischen den beiden Tabellen verknüpfen, sodass Sie Sie müssen nicht mühsam alle Verknüpfungsbedingungen manuell eingeben:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

Beachten Sie, dass dies nur wie erwartet funktioniert, wenn keine der Spalten NULL-Werte hat. In MySQL ist NULL! = NULL, sodass jede Zeile mit einem NULL-Wert zurückgegeben wird, auch wenn die zweite Tabelle eine doppelte Zeile enthält.
Kyle Kochis

84
Wenn Sie 300 Spalten haben, sollten Sie Ihre Datenbank neu gestalten.
Iharob Al Asimi

Hey, das funktioniert auch bei mir, danke! Aber wäre das ein Problem, wenn die Zeilen> 300 sind, wie Sie oben erwähnt haben?
Thekucays

Ich bin immer noch verwirrt über die Abfrage übrigens ... was ist, wenn ich zum Beispiel "wo b.FirstName null ist" in "wo b.LastName null ist" ändere? was ist der Unterschied? Es tut mir leid, dass ich das gefragt habe. Ich bin noch neu in SQL: D
Thekucays

184

Sie müssen die Unterauswahl basierend auf einem Spaltennamen durchführen, nicht *.

Wenn Sie beispielsweise ein idFeld haben, das beiden Tabellen gemeinsam ist, können Sie Folgendes tun:

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

Weitere Beispiele finden Sie in der MySQL-Unterabfragesyntax .


1
Danke für die Klarstellung! Aber ich muss die Auswahl der Zeilen wirklich nicht auf ein Feld stützen, da ich an einer Variation eines Feldes in der Zeile interessiert bin ...

Wenn nur wenige Spalten zum Vergleichen vorhanden sind, können Sie einen Join gemäß dem Beispiel von @ Steve durchführen. Wenn Sie tatsächlich nach einem allgemeinen Vergleich von Daten in zwei Tabellen mit vielen Spalten fragen, möchten Sie wahrscheinlich nach einem MySQL-Diff-Tool suchen .
Stennie

2
Beachten Sie, dass dies immer eine leere Menge zurückgibt, wenn die Spalte, die Sie in Tabelle 2 betrachten, Nullen enthält. Kein Problem, wenn Sie es basierend auf dem Primärschlüssel tun, aber relevant für Leute, die versuchen, diese Abfrage in anderen Kontexten zu verwenden.
Mark Amery

4
Aber was ist, wenn wir über Big Data sprechen? Und Tabelle2 enthält zum Beispiel 100 Millionen Zeilen?
Frops

Kluge und kluge Antwort. Danke Kumpel
Anjana Silva

44
SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS wird dir helfen...


2
Gute Antwort, wirtschaftlich für große Datenmengen, danke.
ekerner

Stark. Beste Antwort für große Datenmengen
Ian Chadwick

35

Ein Standard-LEFT JOIN könnte das Problem lösen und sollte auch schneller sein , wenn die Felder beim Join indiziert sind

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null

in Ordnung, ich denke das muss es sein, übrigens warum das WHERE t2.Birthdate Is Nullstatt AND t1.Birthdate = t2.Birthdate?

Denn wenn Sie das hinzufügen, wird jede Zeile zurückgegeben, Sie sagen, dass in der Ausgabe nur Zeilen erscheinen sollten, die nicht in der zweiten Tabelle enthalten sind
Steve

1
Dies ist eine großartige Antwort, da nicht alle Zeilen von zurückgegeben werden müssen Table2!
Dotancohen

Ich stimme zu, tolle Antwort. Ich habe einen Mann-viele-Tisch zwischen 4 Tischen, das UND in den inneren Join zu setzen, wird definitiv wirtschaftlicher sein.
DR.

6

Versuchen:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL

4

Versuchen Sie diese einfache Abfrage. Es funktioniert perfekt.

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);

-3

Dies hat bei mir in Oracle funktioniert:

SELECT a.* 
    FROM tbl1 a 
MINUS 
SELECT b.* 
    FROM tbl2 b;

Die Frage betraf MySQL.
Jelder

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.