Hilfe mit einer WHERE auf einem LEFT JOIN SQL Query
Frage
Ich versuche, eine Abfrage zu erstellen, die eine Spalte angibt, ob ein Benutzer ein Dokument heruntergeladen umfassen werden. Ich habe eine Tabelle HasDownloaded mit den folgenden Spalten genannt: id, DocumentID, memberID. Herausfinden, ob ein Benutzer ein spezifische heruntergeladen Dokument ist einfach; aber ich brauche eine Abfrage zu erzeugen, wo die Ergebnisse wie folgt aussehen:
name id
----------------------
abc NULL
bbb 2
ccc 53
ddd NULL
eee 13
Die ID ist nicht wirklich wichtig; was ich bin interessiert, ist, ob das Dokument heruntergeladen wurde (ist es NULL oder nicht).
Hier ist meine Abfrage:
SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id
WHERE HasDownloaded.memberID = @memberID
Das Problem ist, wird dies nur Werte zurück, wenn ein Eintrag für den angegebenen Benutzer in der HasDownloaded Tabelle existiert. Ich möchte diese einfach halten und nur haben Einträge in HasDownloaded für Dokumente, die wurde heruntergeladen. Also, wenn Benutzer 1 abc heruntergeladen hat, bbb und ccc, ich will noch ddd und eee in der resultierenden Tabelle zeigen, nur mit der ID als NULL. Aber die WHERE-Klausel nur gibt mir für welche Werte Einträge vorhanden.
ich nicht viel von einem SQL-Experte bin - gibt es ein Operator, der mir geben wird, was ich hier will? Sollte ich einen anderen Ansatz? Oder ist das unmöglich?
Lösung
Bewegen Sie die Bedingung in der WHERE-Klausel in die Join-Bedingung.
SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id
AND HasDownloaded.memberID = @memberID
Dies ist notwendig, wenn Sie auf eine links beziehen mögen beitreten-ed Tabelle in dem, was sonst die WHERE-Klausel wäre.
Andere Tipps
WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
wäre der normale Weg, das zu tun. Einige würden verkürzen Sie es an:
WHERE COALESCE(HasDownloaded.memberId, @memberId) = @memberId
Sie können, wie Matt B. zeigt, tun Sie es in Ihrer JOIN-Bedingung - aber ich denke, das ist viel wahrscheinlicher, Leute zu verwirren. Wenn Sie nicht verstehen, warum es um die Klausel JOIN funktioniert bewegt, dann würde ich stark davon vorschlagen bleiben weg.
@ Mark: Ich verstehe, warum die Syntax funktioniert JOIN, aber danke für die Warnung. Ich glaube Ihr Vorschlag intuitiver ist. Ich war gespannt, was effizienter war. Also lief ich einen schnellen Test (das war eher simpel, ich habe Angst, über nur 14 Zeilen und 10 Versuche):
In der JOIN-Bedingung:
AND HasDownloaded.memberID = @memberID
- Client Bearbeitungszeit: 4.6
- Gesamtausführungszeit: 35.5
- Wartezeit auf Server-Antworten: 30,9
In der WHERE-Klausel:
WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
- Client Verarbeitungszeit: 7,7
- Gesamtausführungszeit: 27.7
- Wartezeit auf Server-Antworten: 22.0
Es ist wie die WHERE-Klausel aussieht, ist immer so etwas effizienter. Interessant! Noch einmal vielen Dank an Sie beide für Ihre Hilfe.