sql >> Database teknologi >  >> RDS >> Sqlserver

Hvor skal man bruge Outer Apply

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

  1. PDOException:SQLSTATE[HY000] [2002] php_network_getaddresses:getaddriinfo mislykkedes:Navn eller tjeneste er ikke kendt

  2. Kørsel af et datavarehus på PostgreSQL

  3. Slut dig til tre borde, hvor en af ​​dem ikke har en primær nøgle

  4. Er der en måde at bruge FORALL til at indsætte data fra et array?