EEN LEFT JOIN
moet worden vervangen door OUTER APPLY
in de volgende situaties.
TOP n
resultaten
Overweeg of we Id
moeten selecteren en Name
van Master
en laatste twee datums voor elke Id
van Details
tafel.
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
wat het volgende resultaat vormt
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
Dit zal verkeerde resultaten opleveren, dwz het zal alleen de laatste twee datumgegevens van Details
. opleveren tabel ongeacht Id
ook al doen we mee met Id
. Dus de juiste oplossing is het gebruik van 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 is de werking:In LEFT JOIN
, TOP 2
datums worden toegevoegd aan de MASTER
alleen na het uitvoeren van de query in de afgeleide tabel D
. In OUTER APPLY
, het maakt gebruik van deelname aan WHERE M.ID=D.ID
binnen de OUTER APPLY
, zodat elke ID
in Master
wordt samengevoegd met TOP 2
datums die het volgende resultaat opleveren.
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
LEFT JOIN
nodig hebben functionaliteit met behulp van functions
.
OUTER APPLY
kan worden gebruikt als vervanging met LEFT JOIN
wanneer we resultaat moeten krijgen van Master
tabel en een function
.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
En de functie komt hier.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE [email protected]
)
wat het volgende resultaat opleverde
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
NULL
waarden bij het ongedaan maken van de draaiing
Bedenk dat je de onderstaande tabel hebt
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
Wanneer u UNPIVOT
gebruikt om FROMDATE
. te brengen EN TODATE
naar één kolom, verwijdert het NULL
waarden standaard.
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
wat het onderstaande resultaat oplevert. Merk op dat we het record van Id
. hebben gemist 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
In dergelijke gevallen een APPLY
kan worden gebruikt (ofwel CROSS APPLY
of OUTER APPLY
, die uitwisselbaar is).
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
wat het volgende resultaat vormt en Id
. behoudt waarbij de waarde 3
. is
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