sql >> Database >  >> RDS >> Sqlserver

Waar te gebruiken Outer Apply

EEN LEFT JOIN moet worden vervangen door OUTER APPLY in de volgende situaties.

1. Als we twee tabellen willen samenvoegen op basis van 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

2. Wanneer we 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

3. Behoud 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


  1. Berichten en opmerkingen verwijderen uit Action Scheduler

  2. Gegevens aggregeren met OVERPARTITIE op datum

  3. De SQL Server-hoofddatabase herstellen

  4. Hoe te SELECTEREN uit de kolom van het objecttype in Oracle 11g?