Ein LEFT JOIN
sollte durch OUTER APPLY
ersetzt werden in folgenden Situationen.
1. Wenn wir zwei Tabellen basierend auf TOP n
verbinden möchten Ergebnisse
Überlegen Sie, ob wir Id
auswählen müssen und Name
von Master
und die letzten beiden Daten für jede Id
aus Details
Tabelle.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
LEFT JOIN
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID
was das folgende Ergebnis bildet
x------x---------x--------------x-------x
| Id | Name | PERIOD | QTY |
x------x---------x--------------x-------x
| 1 | A | 2014-01-13 | 10 |
| 1 | A | 2014-01-12 | 20 |
| 2 | B | NULL | NULL |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
Dies führt zu falschen Ergebnissen, dh es werden nur die letzten zwei Datumsdaten aus Details
angezeigt Tabelle unabhängig von Id
obwohl wir mit Id
beitreten . Die richtige Lösung ist also die Verwendung von OUTER APPLY
.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
OUTER APPLY
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
WHERE M.ID=D.ID
ORDER BY CAST(PERIOD AS DATE)DESC
)D
Hier ist die Funktionsweise:In LEFT JOIN
, TOP 2
Daten werden mit dem MASTER
verbunden erst nach Ausführung der Abfrage innerhalb der abgeleiteten Tabelle D
. In OUTER APPLY
, verwendet es Joining WHERE M.ID=D.ID
innerhalb der OUTER APPLY
, sodass jede ID
im Master
wird mit TOP 2
verbunden Daten, die folgendes Ergebnis bringen.
x------x---------x--------------x-------x
| Id | Name | PERIOD | QTY |
x------x---------x--------------x-------x
| 1 | A | 2014-01-13 | 10 |
| 1 | A | 2014-01-12 | 20 |
| 2 | B | 2014-01-08 | 40 |
| 2 | B | 2014-01-06 | 30 |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
2. Wenn wir LEFT JOIN
brauchen Funktionalität mit functions
.
OUTER APPLY
kann als Ersatz mit LEFT JOIN
verwendet werden wenn wir das Ergebnis von Master
erhalten müssen Tabelle und eine function
.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
Und die Funktion gehört hierher.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE [email protected]
)
was zu folgendem Ergebnis geführt hat
x------x---------x--------------x-------x
| Id | Name | PERIOD | QTY |
x------x---------x--------------x-------x
| 1 | A | 2014-01-13 | 10 |
| 1 | A | 2014-01-11 | 15 |
| 1 | A | 2014-01-12 | 20 |
| 2 | B | 2014-01-06 | 30 |
| 2 | B | 2014-01-08 | 40 |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
3. Behalten Sie NULL
bei Werte beim Entpivotieren
Stellen Sie sich vor, Sie haben die folgende Tabelle
x------x-------------x--------------x
| Id | FROMDATE | TODATE |
x------x-------------x--------------x
| 1 | 2014-01-11 | 2014-01-13 |
| 1 | 2014-02-23 | 2014-02-27 |
| 2 | 2014-05-06 | 2014-05-30 |
| 3 | NULL | NULL |
x------x-------------x--------------x
Wenn Sie UNPIVOT
verwenden um FROMDATE
zu bringen UND TODATE
zu einer Spalte, wird NULL
eliminiert Standardwerte.
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
was das folgende Ergebnis erzeugt. Beachten Sie, dass wir den Eintrag von Id
übersehen haben Zahl 3
x------x-------------x
| Id | DATES |
x------x-------------x
| 1 | 2014-01-11 |
| 1 | 2014-01-13 |
| 1 | 2014-02-23 |
| 1 | 2014-02-27 |
| 2 | 2014-05-06 |
| 2 | 2014-05-30 |
x------x-------------x
In solchen Fällen ein APPLY
verwendet werden (entweder CROSS APPLY
oder OUTER APPLY
, die austauschbar ist).
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
was das folgende Ergebnis bildet und Id
behält wobei sein Wert 3
ist
x------x-------------x
| Id | DATES |
x------x-------------x
| 1 | 2014-01-11 |
| 1 | 2014-01-13 |
| 1 | 2014-02-23 |
| 1 | 2014-02-27 |
| 2 | 2014-05-06 |
| 2 | 2014-05-30 |
| 3 | NULL |
x------x-------------x