Wie schließe ich Zeilen aus, die nicht mit einer anderen Tabelle verknüpft sind?

83

Ich habe zwei Tabellen, eine hat einen Primärschlüssel, die andere einen Fremdschlüssel.

Ich möchte Daten nur dann aus der Primärtabelle abrufen, wenn die Sekundärtabelle keinen Eintrag enthält, der ihren Schlüssel enthält. Eine Art Gegenteil eines einfachen inneren Joins, der nur Zeilen zurückgibt, die durch diesen Schlüssel zusammengefügt werden.

Chaddeus
quelle

Antworten:

262

Alt-Text

SELECT <select_list> 
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL

Vollständiges Bild von join Alt-Text

Aus dem Artikel: http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx

Pranay Rana
quelle
8
endlich! Warum haben sie diese nicht in Lehrbüchern und warum hatten meine Dozenten an der Uni diese nicht?! Sie verwendeten die schlechtesten Erklärungen der Welt, die diesen nicht annähernd nahe kamen!
Python29033
4
Das ist Gold. Ich hasse es, einen Kommentar zu schreiben, der keinen Inhalt hat, sondern ein überschwängliches Lob, aber komm schon! Dies ist eine großartige Antwort. Vielen Dank, @Pranay Rana.
0xbe5077ed
1
Bitte erklären Sie mir, warum B.Key IS NULLaber wir noch vergleichbar A.Key = B.Key?
Do Nhu Vy
1
@DoNhuVy einfach, der Vergleich ist in der "ON" -Klausel, in einem LEFT- oder RIGHT-Join, wenn keine übereinstimmende Zeile vorhanden ist, wird eine Zeile mit allen NULL-Werten verbunden. Anschließend testen Sie, ob IS NULL vorhanden ist, um festzustellen, dass keine übereinstimmende Zeile vorhanden ist . (Dies funktioniert übrigens nur, wenn das Feld, das Sie testen, NICHT NULL ist, dh aus einem anderen Grund nicht NULL haben kann)
Gregory Magarshak
Ich verwende die folgende Abfrage: SELECT A. * FROM #PurgeFilesListNew A FULL OUTER JOIN #DoNotPurgeFilesListNew B ON A.JobFileId = B.JobFileId UND A.AccountID = B.AccountID WHERE A.JobFileId ist NULL ODER B.JobFileId ist NULL AND B.JobFileId A.AccountID IST NULL ODER B.AccountID IST NULL Grundsätzlich habe ich zwei, die zwei Werte in der "ON" -Klausel vergleichen. Es funktioniert einwandfrei, aber die Abfrage gibt eine Nullzeile für die Zeilen zurück, die nicht übereinstimmen. Wie kann man das lösen? Bitte helfen Sie
HarshSharma
9
SELECT
   *
FROM
   primarytable P
WHERE
   NOT EXISTS (SELECT * FROM secondarytable S
     WHERE
         P.PKCol = S.FKCol)

Im Allgemeinen , (NOT) EXISTSist eine bessere Wahl dann (NOT) INoder(LEFT) JOIN

gbn
quelle
Nun, er hat nicht gepostet, was DBRMS verwendet wird, aber in MySql LEFT JOINübertrifft esNOT EXIST
The Scrum Meister
@ The Scrum Meister: Habe ich schneller gesagt? Suchen Sie nach IN vs EXISTS vs JOIN, um die semantischen und logischen Unterschiede zu entdecken ...
gbn
@gbn Sorry, ich dachte mit "bessere Wahl" meinst du schneller. Können Sie dann bitte erklären, auf welche Weise es eine bessere Wahl ist? explainextended.com/2009/09/18/…
The Scrum Meister
1
@ The Scrum Meister: Im Allgemeinen benötigt jede Art von JOIN ein DISTINCT. NOT IN mit einer Null in der Liste ergibt false. IN / EXISTS verhalten sich gleich. Das einzige "sichere" Konstrukt ist jedoch (NICHT) EXISTIERT, es sei denn, Sie mögen Inkonsistenz
gbn
4

Verwenden Sie einen linken Join "nicht vorhanden":

SELECT p.*
FROM primary_table p LEFT JOIN second s ON p.ID = s.ID
WHERE s.ID IS NULL
Der Scrum Meister
quelle
3
SELECT P.*
FROM primary_table P
LEFT JOIN secondary_table S on P.id = S.p_id
WHERE S.p_id IS NULL
Tommi
quelle
2
Haben Sie eine Frage. Wenn wir die Bedingung verwenden P.key = S.keyund dann sagen where S.key IS NULL, macht das dann nicht auch P.key null?
Somjit
3

Eine andere Lösung ist:

SELECT * FROM TABLE1 WHERE id NOT IN (SELECT id FROM TABLE2)
Ali Akbar
quelle
2

Wenn Sie die Spalten aus der ersten Tabelle auswählen möchten, die auch in der zweiten Tabelle vorhanden sind, können Sie sie in diesem Fall auch verwenden EXCEPT. In diesem Fall können auch die Spaltennamen unterschiedlich sein, der Datentyp sollte jedoch gleich sein.

Beispiel:

select ID, FName
from FirstTable
EXCEPT
select ID, SName
from SecondTable
Anil Soman
quelle
0

Dies war in COGNOS hilfreich, da das Erstellen einer SQL-Anweisung "Nicht in" in Cognos zulässig war, die Ausführung jedoch zu lange dauerte. Ich hatte Tabelle A manuell codiert, um sie in Cognos als A.key "nicht in" B.key mit Tabelle B zu verbinden, aber die Abfrage dauerte zu lange / gab nach 5 Minuten keine Ergebnisse zurück.

Für alle anderen, die nach einer "NOT IN" -Lösung in Cognos suchen, habe ich Folgendes getan. Erstellen Sie eine Abfrage, die Tabelle A und B mit einem LEFT JOIN in Cognos verbindet, indem Sie den Verknüpfungstyp auswählen: Tabelle A. Der Schlüssel hat in Tabelle B Werte von "0 bis N" und fügt dann einen Filter (diese entsprechen den Where-Klauseln) für: Tabelle B hinzu Schlüssel ist NULL.

Lief schnell und wie ein Zauber.

JennyB
quelle