Exemple :
SET NOCOUNT ON;
SET IMPLICIT_TRANSACTIONS ON;
CREATE TABLE MyTable (MyID INT PRIMARY KEY);
GO
INSERT MyTable (MyID)
VALUES (11), (22), (33), (44), (55);
PRINT 'Test MyCTE:';
WITH MyCTE
AS (
SELECT *, ROW_NUMBER()OVER(ORDER BY MyID) AS RowNum
FROM MyTable
)
SELECT *
FROM MyCTE crt
LEFT JOIN MyCTE prev ON crt.RowNum=prev.RowNum+1;
ROLLBACK;
Si vous exécutez le script précédent dans SSMS (appuyez sur Ctrl+M
-> Actual Execution Plan) alors vous obtiendrez ce plan d'exécution pour la dernière requête :
Dans ce cas, le CTE est exécuté une fois pour crt
alias et cinq (!) fois pour prev
alias, une fois pour chaque ligne de crt
.
Donc, la réponse à cette question
est both
:une fois par requête (crt
) et une fois par ligne (prev
:une fois pour chaque for de crt
).
Pour optimiser cette requête, pour commencer,1) Vous pouvez essayer de stocker les résultats de CTE (MyCTE
ou Query
) dans une variable de table ou une table temporaire
2) Définissez la clé primaire de cette table comme étant la ou les colonnes de jointure,
3) Réécrivez la requête finale pour utiliser cette variable de table ou cette table temporaire.
Bien sûr, vous pouvez essayer de réécrire la requête finale sans cette auto-jointure entre CTE.