Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Où utiliser l'application externe

Une LEFT JOIN doit être remplacé par OUTER APPLY dans les situations suivantes.

1. Si nous voulons joindre deux tables basées sur TOP n résultats

Considérez si nous devons sélectionner Id et Name de Master et les deux dernières dates pour chaque Id à partir de Details tableau.

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

qui forme le résultat suivant

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

Cela entraînera des résultats erronés, c'est-à-dire qu'il n'apportera que les données des deux dernières dates de Details table indépendamment de Id même si nous nous joignons avec Id . Donc, la bonne solution utilise 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

Voici le fonctionnement :En LEFT JOIN , TOP 2 les dates seront jointes au MASTER uniquement après avoir exécuté la requête dans la table dérivée D . Dans OUTER APPLY , il utilise la jointure WHERE M.ID=D.ID à l'intérieur de OUTER APPLY , de sorte que chaque ID en Master sera rejoint par TOP 2 dates qui apporteront le résultat suivant.

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. Quand nous avons besoin de LEFT JOIN fonctionnalité à l'aide de functions .

OUTER APPLY peut être utilisé en remplacement de LEFT JOIN quand nous devons obtenir le résultat de Master table et une function .

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

Et la fonction va ici.

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

qui a généré le résultat suivant

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. Conserver NULL valeurs lors du non-pivot

Considérez que vous avez le tableau ci-dessous

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

Lorsque vous utilisez UNPIVOT pour apporter FROMDATE ET TODATE à une colonne, cela éliminera NULL valeurs par défaut.

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

qui génère le résultat ci-dessous. Notez que nous avons manqué l'enregistrement de Id numéro 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

Dans de tels cas, un APPLY peut être utilisé (soit CROSS APPLY ou OUTER APPLY , qui est interchangeable).

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

qui forme le résultat suivant et conserve Id où sa valeur est 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