sql >> Databasteknik >  >> RDS >> Sqlserver

Körs WITH-satsen en gång per fråga eller en gång per rad?

Exempel:

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;

Om du kör tidigare skript i SSMS (tryck på Ctrl+M -> Faktisk exekveringsplan) så får du denna exekveringsplan för den sista frågan:

I det här fallet exekveras CTE en gång för crt alias och fem (!) gånger för prev alias, en gång för varje rad från crt .

Så svaret på denna fråga

är both :en gång per fråga (crt ) och en gång per rad (prev :en gång för varje för från crt ).

För att optimera den här frågan, till att börja med,1) Du kan försöka lagra resultaten från CTE (MyCTE eller Query ) till en tabellvariabel eller en tillfällig tabell

2) Definiera den här tabellens primärnyckel som kopplingskolumn(erna),

3) Skriv om den sista frågan för att använda denna tabellvariabel eller temporära tabell.

Naturligtvis kan du försöka skriva om den slutliga frågan utan denna självkoppling mellan CTE.




  1. Sequelize — använd UNIX-tidsstämpel för DATE-fält

  2. Pivottabell returnerar endast 1 rad

  3. Använda en utlösare för att implementera en begränsning för kontroll av främmande nyckel

  4. Hur skapar man en fråga i MySQL för att subtrahera på varandra följande rader baserat på datum och ett distinkt fält?