2016-04-15 5 views
1

Die folgende Abfrage, die eine Zeile für jeden Reading_Type zurückgeben soll, plus den gespeicherten Lesewert für diesen Reading_Type und das Datum oder 0 falls nein Das Lesen wurde gespeichert.SQL JOIN - gibt eine Zeile für jede Tabelle A zurück, unabhängig davon, ob Tabelle B Werte enthält oder nicht

SELECT 
     t.* 
    , ISNULL(r.Reading, 0) AS Reading 
FROM 
    Reading_Type t 
LEFT JOIN 
    Reading r ON t.Reading_Type_ID = r.Reading_Type_ID 
WHERE 
    r.Reading_Date = @date 
    OR r.Reading_Date IS NULL 
  • Es tut Arbeit, wenn es keine Lesungen für ein beliebiges Datum gespeichert
  • Es tut Arbeit, wenn die einzigen gespeicherten Messwerte für das ausgewählte Datum sind.
  • Es tut nicht Arbeit, wenn ein Reading_Type ein gerettet hat für Datum X Lesen, keine Lese für Datum Y gespeichert, und die Suche nach Datum Y.

Reading_Type Tabelle:

Reading_Type_ID Reading_Type 
----------------------------- 
1    Red 
2    Blue 
3    Green 

Reading Tabelle (Tabelle leer ist):

Reading_ID Reading_Type_ID Reading Reading_Date 
----------------------------------------------------- 

Abfrage mit @date = April 15, 2016 Rückgabe:

Reading_Type_ID Reading_Type Reading 
---------------------------------------- 
1    Red   0 
2    Blue   0 
3    Green   0 

Reading Tabelle (Tabelle Daten für April 15 hat):

Reading_ID Reading_Type_ID Reading Reading_Date 
----------------------------------------------------- 
1   1    5  April 15, 2016 
2   3    8  April 15, 2016 

Abfrage mit @date = April 15, 2016 Rückkehr:

Reading_Type_ID Reading_Type Reading 
---------------------------------------- 
1    Red   5 
2    Blue   0 
3    Green   8 

Abfrage mit @date = April 7, 2016 Rückkehr:

Reading_Type_ID Reading_Type Reading 
---------------------------------------- 
1    Red   0 
3    Green   0 

Die dritte Abfrage sollte immer noch eine Zeile für Reading_Type = Blau mit 0 für Reading zurückgeben. Wie behebe ich meine Anfrage?

+0

vielleicht gibt es keine Reading_Type für 7. April 2016? – FLICKER

+0

@FLICKER Ich denke, das ist der Punkt. – TZHX

Antwort

4

Ihr WHERE-Kriterium verursacht Ihr Filterproblem (das habe ich selbst nur millionenfach getan). Versuchen Sie stattdessen:

Lassen Sie die WHERE-Klausel in diesem Fall (außer Sie möchten Ihre Daten weiter filtern).

Hier einige Informationen, die Detail dieses SQL-Funktion hilft: Specifying Joins in FROM or WHERE clauses

+0

Dies ist ein LINKER JOIN, was bedeutet, dass jeder Datensatz aus der Tabelle Reading_Type abgerufen wird. Das OP hat eine WHERE-Klausel verwendet, die das herausgefiltert hat. Durch Verschieben der Kriterien in die JOIN-Klausel werden jedoch alle Datensätze aus der LEFT-Tabelle sowie alle Datensätze zurückgegeben, die in der RIGHT-Tabelle übereinstimmen. Wenn keine Übereinstimmung vorhanden ist, wird ein NULL zurückgegeben, der von der ISNULL() - Funktion der SELECT-Anweisung auf 0 gesetzt wird. –

-1

Die Abfrage wird das tun, was Sie es sind zu fragen. Es wird ein linker Join ausgeführt (der alle Datensätze von t und Datensätze von r zurückgibt, wenn diese existieren) ... und dann Ihre WHERE-Bedingung anwendet. Wenn r.Reading_Date weder NULL noch @date ist, werden die Datensätze aus dieser Abfrage aus der Ergebnismenge ausgeschlossen.

Ich denke, was Sie wollen, wenn ich es richtig verstanden habe, ist eine linke auf einem subselect kommen ... so etwas wie folgt aus:

SELECT 
    t.*, ISNULL(r.Reading, 0) AS Reading 
FROM 
Reading_Type t 
LEFT JOIN (
    SELECT Reading_Type_ID, Reading 
    FROM Reading 
    WHERE Reading_Date = @date 
    OR Reading_Date IS NULL 
) r 
ON t.Reading_Type_ID = r.Reading_Type_ID 
+0

... ist das nicht der gleiche Code wie in der Frage? – TZHX

+0

Es war ja, ich habe mid edit gepostet, aus Versehen ... korrigiert. –

1

wenn r.Reading_Date kann null sein und Sie möchten diese dann einschließen

Verwandte Themen