Es gibt verschiedene Situationen , in denen man nicht vermeiden kann CROSS APPLY
oder OUTER APPLY
.
Angenommen, Sie haben zwei Tabellen.
MASTER TABLE
x------x--------------------x
| Id | Name |
x------x--------------------x
| 1 | A |
| 2 | B |
| 3 | C |
x------x--------------------x
DETAILS TABELLE
x------x--------------------x-------x
| Id | PERIOD | QTY |
x------x--------------------x-------x
| 1 | 2014-01-13 | 10 |
| 1 | 2014-01-11 | 15 |
| 1 | 2014-01-12 | 20 |
| 2 | 2014-01-06 | 30 |
| 2 | 2014-01-08 | 40 |
x------x--------------------x-------x
CROSS APPLY
Es gibt viele Situation , wo wir ersetzen müssen INNER JOIN
mitCROSS APPLY
.
1. Wenn wir 2 Tabellen zu TOP n
Ergebnissen mit verbinden möchtenINNER JOIN
Funktionalität
Überlegen Sie, ob wir müssen wählen Id
und Name
aus Master
und die letzten beiden Tage , für jeden Id
aus Details table
.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
INNER JOIN
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID
Die obige Abfrage generiert das folgende Ergebnis.
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 |
x------x---------x--------------x-------x
Es wurden Ergebnisse für die letzten beiden Daten mit den letzten beiden Daten generiert Id
und diese Datensätze dann nur in der äußeren Abfrage am verknüpft Id
, was falsch ist. Um dies zu erreichen, müssen wir verwenden CROSS APPLY
.
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
CROSS APPLY
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
WHERE M.ID=D.ID
ORDER BY CAST(PERIOD AS DATE)DESC
)D
und bildet er folgendes Ergebnis.
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 |
x------x---------x--------------x-------x
Hier ist die Arbeit. Die Abfrage im Inneren CROSS APPLY
kann auf die äußere Tabelle verweisen, wo INNER JOIN
dies nicht möglich ist (löst einen Kompilierungsfehler aus). Wenn Sie die letzten beiden Daten gefunden haben, erfolgt der Beitritt innerhalb von, CROSS APPLY
dhWHERE M.ID=D.ID
.
2. Wenn wir INNER JOIN
Funktionalität mit Funktionen benötigen .
CROSS APPLY
kann als Ersatz verwendet werden, INNER JOIN
wenn wir Ergebnisse aus Master
Tabelle und a erhalten müssen function
.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
CROSS APPLY dbo.FnGetQty(M.ID) C
Und hier ist die Funktion
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE ID=@Id
)
welches das folgende Ergebnis erzeugte
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 |
x------x---------x--------------x-------x
AUSSEN ANWENDEN
1. Wenn wir 2 Tabellen zu TOP n
Ergebnissen mit verbinden möchtenLEFT JOIN
Funktionalität
Überlegen Sie, ob wir ID und Name aus Master
und die letzten beiden Daten für jede ID aus der Details
Tabelle auswählen müssen .
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
welches 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 Daten der letzten beiden Daten aus der Details
Tabelle angezeigt, unabhängig davon Id
, ob wir uns anschließen oder nicht Id
. Die richtige Lösung ist also 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
welches das folgende gewünschte 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 | 2014-01-08 | 40 |
| 2 | B | 2014-01-06 | 30 |
| 3 | C | NULL | NULL |
x------x---------x--------------x-------x
2. Wenn wir LEFT JOIN
Funktionalität mit benötigen functions
.
OUTER APPLY
kann als Ersatz verwendet werden, LEFT JOIN
wenn wir Ergebnisse aus Master
Tabelle und a erhalten müssen function
.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
Und die Funktion geht hier.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE ID=@Id
)
welches das folgende Ergebnis erzeugte
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
Gemeinsames Merkmal von CROSS APPLY
undOUTER APPLY
CROSS APPLY
oder OUTER APPLY
kann verwendet werden, um NULL
beim Schwenken Werte beizubehalten, die austauschbar sind.
Angenommen, 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
bringen FROMDATE
und TODATE
zu einer Spalte, wird es beseitigen NULL
Werte standardmäßig.
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
Dies erzeugt das folgende Ergebnis. Beachten Sie, dass wir den Datensatz der Id
Nummer verpasst haben3
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 ist ein CROSS APPLY
oder OUTER APPLY
nützlich
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
Dies bildet das folgende Ergebnis und behält bei, Id
wo sein Wert ist3
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