En LEFT JOIN
bør erstattes med OUTER APPLY
i følgende situationer.
1. Hvis vi ønsker at forbinde to tabeller baseret på TOP n
resultater
Overvej om vi skal vælge Id
og Name
fra Master
og sidste to datoer for hver Id
fra Details
tabel.
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
som danner følgende resultat
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
Dette vil give forkerte resultater, dvs. det vil kun bringe de seneste to datoer fra Details
tabel uanset Id
selvom vi tilslutter os med Id
. Så den rigtige løsning er at bruge 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
Her er funktionen:I LEFT JOIN
, TOP 2
datoer vil blive knyttet til MASTER
kun efter at have udført forespørgslen i den afledte tabel D
. I OUTER APPLY
, den bruger joining WHERE M.ID=D.ID
inde i OUTER APPLY
, så hver ID
i Master
vil blive sammenføjet med TOP 2
datoer, som vil give følgende resultat.
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. Når vi har brug for LEFT JOIN
funktionalitet ved hjælp af functions
.
OUTER APPLY
kan bruges som erstatning med LEFT JOIN
når vi har brug for at få resultater fra Master
tabel og en function
.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
Og funktionen går her.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE [email protected]
)
som genererede følgende resultat
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. Behold NULL
værdier ved unpivotering
Overvej at du har nedenstående tabel
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
Når du bruger UNPIVOT
for at bringe FROMDATE
OG TODATE
til én kolonne, vil det fjerne NULL
værdier som standard.
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
som genererer nedenstående resultat. Bemærk, at vi har savnet registreringen af Id
nummer 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
I sådanne tilfælde en APPLY
kan bruges (enten CROSS APPLY
eller OUTER APPLY
, som er udskiftelig).
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
som danner følgende resultat og bevarer Id
hvor dens værdi er 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 |
| 3 | NULL |
x------x-------------x