Une LEFT JOIN doit être remplacé par OUTER APPLY dans les situations suivantes.
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
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 example@sqldat.com
)
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
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