sql >> Databáze >  >> RDS >> Sqlserver

Kde použít Outer Apply

LEFT JOIN by měla být nahrazena OUTER APPLY v následujících situacích.

1. Pokud chceme spojit dvě tabulky na základě TOP n výsledky

Zvažte, zda musíme vybrat Id a Name z Master a poslední dvě data pro každé Id z Details tabulka.

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

který tvoří následující výsledek

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

To přinese špatné výsledky, tj. přinese pouze poslední dvě data z Details tabulky bez ohledu na Id i když se připojíme pomocí Id . Správným řešením je tedy použití 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

Zde je funkční:V LEFT JOIN , TOP 2 data budou spojena s MASTER až po provedení dotazu v odvozené tabulce D . V OUTER APPLY , používá spojení WHERE M.ID=D.ID uvnitř OUTER APPLY , takže každé Id v Master bude spojen s TOP 2 data, která přinesou následující výsledek.

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. Když potřebujeme LEFT JOIN funkčnost pomocí functions .

OUTER APPLY lze použít jako náhradu za LEFT JOIN když potřebujeme získat výsledek z Master tabulka a function .

SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C

A funkce je tady.

CREATE FUNCTION FnGetQty 
(   
    @Id INT 
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT ID,PERIOD,QTY 
    FROM DETAILS
    WHERE [email protected]
)

který vygeneroval následující výsledek

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. Zachovat NULL hodnoty při odklopení

Zvažte, že máte níže uvedenou tabulku

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

Když použijete UNPIVOT aby přinesl FROMDATE AND TODATE do jednoho sloupce, odstraní NULL hodnoty ve výchozím nastavení.

SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P

který generuje níže uvedený výsledek. Všimněte si, že jsme vynechali záznam Id číslo 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

V takových případech APPLY lze použít (buď CROSS APPLY nebo OUTER APPLY , který je zaměnitelný).

SELECT DISTINCT ID,DATES
FROM MYTABLE 
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)

který tvoří následující výsledek a zachovává Id kde jeho hodnota je 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. Jak mohu filtrovat znaky Emoji z mého vstupu, abych mohl uložit v MySQL <5.5?

  2. Jak vytvořit dotaz v Drupal 8

  3. Proč PDO_MySQL nevrátí celé číslo?

  4. Únik paměti ovladače Oracle - Tomcat