Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wird die WITH-Anweisung einmal pro Abfrage oder einmal pro Zeile ausgeführt?

Beispiel:

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;

Wenn Sie das vorherige Skript in SSMS ausführen (drücken Sie Ctrl+M -> Tatsächlicher Ausführungsplan), dann erhalten Sie diesen Ausführungsplan für die letzte Abfrage:

In diesem Fall wird der CTE einmal für crt ausgeführt Alias ​​und fünf (!) Mal für prev Alias, einmal für jede Zeile von crt .

Also, die Antwort auf diese Frage

ist both :einmal pro Abfrage (crt ) und einmal pro Zeile (prev :einmal für jeden von crt ).

Um diese Abfrage zunächst zu optimieren,1) können Sie versuchen, die Ergebnisse von CTE (MyCTE) zu speichern oder Query ) in eine Tabellenvariable oder eine temporäre Tabelle

2) Definieren Sie den Primärschlüssel dieser Tabelle als Join-Spalte(n),

3) Schreiben Sie die letzte Abfrage neu, um diese Tabellenvariable oder temporäre Tabelle zu verwenden.

Natürlich können Sie versuchen, die endgültige Abfrage ohne diese Selbstverknüpfung zwischen CTE neu zu schreiben.