Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A következőkre vonatkozik:SQL Server
Azure SQL Database
Felügyelt Azure SQL-példány
Azure Synapse Analytics
Elemzési platformrendszer (PDW)
SQL Analytics-végpont a Microsoft Fabricben
Raktár a Microsoft Fabricben
SQL-adatbázis a Microsoft Fabricben
Egy ideiglenes elnevezett eredménykészletet határoz meg, amelyet közös táblakifejezésnek (CTE) nevezünk. Ez egy egyszerű lekérdezésből származik, és egyetlen SELECT, , INSERT, UPDATE, MERGEvagy DELETE utasítás végrehajtási hatókörén belül van definiálva. Ez a záradék egy CREATE VIEW utasításban is használható a meghatározó SELECT utasítás részeként. A gyakori táblakifejezések magukra mutató hivatkozásokat is tartalmazhatnak. Ezt rekurzív gyakori táblakifejezésnek nevezzük.
További információ: Gyakori táblakifejezéseket használó rekurzív lekérdezések.
Transact-SQL szintaxis konvenciók
Syntax
[ WITH <common_table_expression> [ , ...n ] ]
<common_table_expression>::=
expression_name [ ( column_name [ , ...n ] ) ]
AS
( CTE_query_definition )
Arguments
expression_name
A közös táblakifejezés érvényes azonosítója.
expression_name különböznie kell az ugyanabban WITH <common_table_expression> a záradékban definiált többi közös táblakifejezés nevétől, de expression_name ugyanaz lehet, mint egy alaptábla vagy nézet neve. A lekérdezésben szereplő expression_name hivatkozás a közös táblakifejezést használja, nem pedig az alapobjektumot.
column_name
Egy oszlopnevet ad meg a közös táblakifejezésben. Egyetlen CTE-definícióban nem lehet ismétlődő neveket létrehozni. A megadott oszlopnevek számának meg kell egyeznie a CTE_query_definition eredményhalmazában szereplő oszlopok számával. Az oszlopnevek listája csak akkor választható, ha az összes eredményként kapott oszlop neve szerepel a lekérdezésdefinícióban.
CTE_query_definition
Olyan utasítást SELECT ad meg, amelynek eredményhalmaza kitölti a közös táblakifejezést. A SELECTCTE_query_definition utasításának meg kell felelnie a nézet létrehozásához szükséges követelményeknek, kivéve, ha a CTE nem definiálhat másik CTE-t. További információkért tekintse meg a Megjegyzések szakaszt és a CREATE VIEW nézetet.
Ha egynél több CTE_query_definition van definiálva, a lekérdezésdefiníciókat a következő halmaz-operátorok egyikének kell összekapcsolnia: UNION ALL, UNION, EXCEPTvagy INTERSECT.
Használati irányelvek
A gyakori táblakifejezések lekérdezési eredményei nem materializáltak. A névvel ellátott eredményhalmazra mutató minden külső hivatkozáshoz újra végre kell hajtani a definiált lekérdezést. Az olyan lekérdezések esetében, amelyek több hivatkozást igényelnek az elnevezett eredményhalmazra, fontolja meg inkább egy ideiglenes objektum használatát.
Nem hajthat végre tárolt eljárást egy közös táblakifejezésben.
A rekurzív és a nem rekurzív CT-kkel kapcsolatos használati irányelvekért tekintse meg a következő szakaszokat.
Nem rekurzív gyakori táblakifejezések irányelvei
Note
Az alábbi irányelvek nem rekurzív gyakori táblakifejezésekre vonatkoznak. A rekurzív közös táblakifejezésekre vonatkozó irányelvekért tekintse meg a rekurzív gyakori táblakifejezések irányelveit.
A CTE-t egyetlen SELECT, , INSERT, UPDATE, MERGEvagy DELETE utasításnak kell követnie, amely a CTE-oszlopok egy részét vagy egészét hivatkozik. A CTE egy utasításban CREATE VIEW is megadható a nézet definiáló SELECT utasításának részeként.
Több CTE-lekérdezésdefiníció definiálható nem rekurzív CTE-ben. A definíciókat a következő operátorok egyikével kell kombinálni: UNION ALL, UNION, INTERSECTvagy EXCEPT.
A CTE hivatkozhat magára és a korábban definiált CTE-kre ugyanabban WITH a záradékban. A továbbítási hivatkozás nem engedélyezett.
A CTE-ben egynél WITH több záradék megadása nem engedélyezett. Ha például egy CTE_query_definition alqueryt tartalmaz, akkor az alquery nem tartalmazhat beágyazott WITH záradékot, amely egy másik CTE-t határoz meg.
A Beágyazott CTE-kkel kapcsolatos további információkért lásd: Beágyazott közös táblakifejezés (CTE) a Fabric adattárházakban (Transact-SQL).
A következő záradékok nem használhatók a CTE_query_definition:
-
ORDER BY(kivéve, ha egyTOPvagyOFFSET/FETCHtöbb záradék van megadva) INTO-
OPTIONzáradék lekérdezési tippekkel 1 FOR BROWSE
1 A OPTION záradék nem használható CTE-definícióban. Csak a legkülső SELECT utasításban használható.
Ha CTE-t használ egy köteg részét képező utasításban, az előtte lévő utasítást pontosvesszővel kell követni.
A CTE-ra hivatkozó lekérdezések a kurzor definiálására használhatók.
A távoli kiszolgálókon lévő táblákra a CTE-ben lehet hivatkozni.
CTE végrehajtásakor a CTE-ra hivatkozó tippek ütközhetnek más, a CTE alapjául szolgáló táblák elérésekor felfedezett tippekkel, ugyanúgy, mint a lekérdezésekben lévő nézetekre hivatkozó tippek. Ha ez történik, a lekérdezés hibát ad vissza.
Rekurzív gyakori táblakifejezések irányelvei
Note
A rekurzív közös táblakifejezések meghatározására az alábbi irányelvek vonatkoznak. A nem rekurzív CTE-kre vonatkozó irányelvekért tekintse meg a nem rekurzív gyakori táblakifejezések irányelveit.
A rekurzív CTE-definíciónak tartalmaznia kell legalább két CTE-lekérdezésdefiníciót, egy horgonytagot és egy rekurzív tagot. Több horgonytag és rekurzív tag definiálható; Azonban minden horgonytag-lekérdezésdefiníciót az első rekurzív tagdefiníció elé kell helyezni. Minden CTE-lekérdezésdefiníció horgonytag, hacsak nem hivatkoznak magára a CTE-ra.
A horgonytagokat a következő operátorok egyikével kell kombinálni: UNION ALL, UNION, INTERSECTvagy EXCEPT.
UNION ALL az utolsó horgonytag és az első rekurzív tag között engedélyezett egyetlen beállítási operátor, több rekurzív tag kombinálásakor.
A horgonyban és a rekurzív tagokban lévő oszlopok számának meg kell egyeznie.
A rekurzív tag oszlopának adattípusának meg kell egyeznie a horgonytag megfelelő oszlopának adattípusával.
A FROM rekurzív tagok záradékának csak egyszer kell hivatkoznia a CTE expression_name.
A rekurzív tagok CTE_query_definition a következő elemek nem engedélyezettek:
SELECT DISTINCTGROUP BY-
PIVOT1 HAVING- Skaláris aggregáció
TOP-
LEFT,RIGHT,OUTER JOIN(INNER JOINengedélyezett) - Subqueries
- Egy CTE_query_definition belüli CTE rekurzív hivatkozására alkalmazott tipp.
1 Ha az adatbázis kompatibilitási szintje 110 vagy magasabb. Tekintse meg az SQL Server 2016 adatbázismotor-funkcióinak kompatibilitástörő változásait.
A rekurzív gyakori táblakifejezések használatára az alábbi irányelvek vonatkoznak:
A rekurzív CTE által visszaadott összes oszlop null értékű, függetlenül a részt vevő
SELECTutasítások által visszaadott oszlopok null értékétől.A helytelenül összeállított rekurzív CTE végtelen ciklust okozhat. Ha például a rekurzív tag lekérdezésdefiníciója ugyanazokat az értékeket adja vissza a szülő- és gyermekoszlopok esetében is, akkor egy végtelen ciklus jön létre. A végtelen ciklus megakadályozása érdekében korlátozhatja egy adott utasításhoz engedélyezett rekurziós szintek számát a
MAXRECURSIONtipp és az0,32767,OPTIONvagyINSERTutasítás záradékaUPDATEközöttiDELETEésSELECTaz abban szereplő érték használatával. Ez lehetővé teszi az utasítás végrehajtásának szabályozását, amíg meg nem oldja a ciklust létrehozó kódhibát. A kiszolgálószintű alapértelmezett érték 100. Ha 0 van megadva, a rendszer nem alkalmaz korlátot. Utasításonként csak egyMAXRECURSIONérték adható meg. További információ: Lekérdezési tippek.A rekurzív gyakori táblakifejezéseket tartalmazó nézet nem használható adatok frissítésére.
A kurzorok a CTE-k használatával definiálhatók lekérdezéseken. A CTE a kurzor eredményhalmazát meghatározó select_statement argumentum. A rekurzív CTE-k esetében csak gyors előremutató és statikus (pillanatkép) kurzorok engedélyezettek. Ha egy rekurzív CTE-ben egy másik kurzortípus van megadva, a rendszer statikussá alakítja a kurzortípust.
A távoli kiszolgálókon lévő táblákra a CTE-ben lehet hivatkozni. Ha a távoli kiszolgálóra a CTE rekurzív tagja hivatkozik, a rendszer minden távoli táblához létrehoz egy spoolt, hogy a táblák helyileg ismételten elérhetők legyenek. Ha CTE-lekérdezésről van szó, akkor az Index Spool/Lazy Spools megjelenik a lekérdezéstervben, és a további
WITH STACKpredikátum is megjelenik. Ez az egyik módszer a megfelelő rekurzió megerősítésére.A CTE rekurzív részében lévő elemzési és aggregátumfüggvényeket a rendszer az aktuális rekurziós szint halmazára alkalmazza, a CTE-hez tartozó készletre nem. Az olyan függvények, mint
ROW_NUMBERaz aktuális rekurziós szint által nekik átadott adatok csak részhalmazán működnek, a CTE rekurzív részére átadott teljes adatkészlet nem. További információ: I. Példa: Elemzési függvények használata a következő rekurzív CTE-ben.
Az Azure Synapse Analytics and Analytics Platform System (PDW) általános táblakifejezései
Az Azure Synapse Analytics and Analytics Platform System (PDW) cte-jeinek jelenlegi implementálása a következő funkciókkal és követelményekkel rendelkezik:
A CTE egy utasításban
SELECTadható meg.A CTE egy utasításban
CREATE VIEWadható meg.A CTE egy (CTAS) utasításban
CREATE TABLE AS SELECTadható meg.A CTE megadható egy
CREATE REMOTE TABLE AS SELECT(CRTAS) utasításban.A CTE megadható egy
CREATE EXTERNAL TABLE AS SELECT(CETAS) utasításban.Egy távoli táblára hivatkozhat egy CTE-ből.
Egy külső táblára hivatkozhat egy CTE-ből.
A CTE-ben több CTE-lekérdezésdefiníció is definiálható.
A CTE-t
SELECTkövethetik ,INSERT,UPDATE,DELETEvagyMERGEutasítások.A saját magára mutató hivatkozásokat (rekurzív közös táblakifejezést) tartalmazó közös táblakifejezések nem támogatottak.
A CTE-ben egynél
WITHtöbb záradék megadása nem engedélyezett. Ha például egy CTE-lekérdezésdefiníció alqueryt tartalmaz, akkor az alkérés nem tartalmazhat beágyazottWITHzáradékot, amely egy másik CTE-t definiál.A
ORDER BYzáradék nem használható a CTE_query_definition, kivéve, ha egyTOPzáradék meg van adva.Ha CTE-t használ egy köteg részét képező utasításban, az előtte lévő utasítást pontosvesszővel kell követni.
A cte-k az általuk készített
sp_prepareutasításokban ugyanúgy viselkednek, mint az APS PDW másSELECTutasításai. Ha azonban a CETAS általsp_prepareelőkészített CETAS részeként használják a CTE-ket, a viselkedés késleltethető az SQL Serverről és más APS PDW-utasításokból a kötés implementálásánaksp_preparemódja miatt. HaSELECTa CTE nem megfelelő oszlopot használ, amely nem létezik a CTE-ben, asp_preparehiba észlelése nélkül halad át, de a hiba a rendszer közbensp_executejelenik meg.
Examples
A. Közös táblakifejezés létrehozása
Az alábbi példa az Adventure Works Cycles egyes értékesítési képviselőinek évi értékesítési rendeléseinek teljes számát mutatja be.
-- Define the CTE expression name and column list.
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)
AS
-- Define the CTE query.
(
SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
)
-- Define the outer query referencing the CTE name.
SELECT SalesPersonID,
COUNT(SalesOrderID) AS TotalSales,
SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID
ORDER BY SalesPersonID, SalesYear;
B. Gyakori táblakifejezés használata a számok és a jelentés átlagainak korlátozásához
Az alábbi példa az értékesítési képviselők összes évre vonatkozó értékesítési rendeléseinek átlagos számát mutatja.
WITH Sales_CTE (SalesPersonID, NumberOfOrders)
AS
(
SELECT SalesPersonID, COUNT(*)
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
GROUP BY SalesPersonID
)
SELECT AVG(NumberOfOrders) AS "Average Sales Per Person"
FROM Sales_CTE;
C. Több CTE-definíció használata egyetlen lekérdezésben
Az alábbi példa bemutatja, hogyan definiálhat több CTE-t egyetlen lekérdezésben. A CTE-lekérdezésdefiníciók elválasztására vesszőt használunk. A FORMAT pénzösszegek pénznemformátumban való megjelenítéséhez használt függvény az SQL Server 2012-ben (11.x) lett bevezetve.
WITH Sales_CTE (SalesPersonID, TotalSales, SalesYear)
AS
-- Define the first CTE query.
(
SELECT SalesPersonID,
SUM(TotalDue) AS TotalSales,
YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
GROUP BY SalesPersonID, YEAR(OrderDate)
), -- Use a comma to separate multiple CTE definitions.
-- Define the second CTE query, which returns sales quota data by year for each sales person.
Sales_Quota_CTE (BusinessEntityID, SalesQuota, SalesQuotaYear)
AS
(
SELECT BusinessEntityID,
SUM(SalesQuota) AS SalesQuota,
YEAR(QuotaDate) AS SalesQuotaYear
FROM Sales.SalesPersonQuotaHistory
GROUP BY BusinessEntityID, YEAR(QuotaDate)
)
-- Define the outer query by referencing columns from both CTEs.
SELECT SalesPersonID,
SalesYear,
FORMAT(TotalSales, 'C', 'en-us') AS TotalSales,
SalesQuotaYear,
FORMAT(SalesQuota, 'C', 'en-us') AS SalesQuota,
FORMAT(TotalSales - SalesQuota, 'C', 'en-us') AS Amt_Above_or_Below_Quota
FROM Sales_CTE
INNER JOIN Sales_Quota_CTE
ON Sales_Quota_CTE.BusinessEntityID = Sales_CTE.SalesPersonID
AND Sales_CTE.SalesYear = Sales_Quota_CTE.SalesQuotaYear
ORDER BY SalesPersonID, SalesYear;
Íme egy részleges eredményhalmaz.
SalesPersonID SalesYear TotalSales SalesQuotaYear SalesQuota Amt_Above_or_Below_Quota
------------- --------- ----------- -------------- ---------- ----------------------------------
274 2005 $32,567.92 2005 $35,000.00 ($2,432.08)
274 2006 $406,620.07 2006 $455,000.00 ($48,379.93)
274 2007 $515,622.91 2007 $544,000.00 ($28,377.09)
274 2008 $281,123.55 2008 $271,000.00 $10,123.55
D. Rekurzív gyakori táblakifejezés használata több rekurziós szint megjelenítéséhez
Az alábbi példa a vezetők és a nekik jelentést készítő alkalmazottak hierarchikus listáját mutatja be. A példa a tábla létrehozásával és feltöltésével dbo.MyEmployees kezdődik.
-- Create an Employee table.
CREATE TABLE dbo.MyEmployees
(
EmployeeID SMALLINT NOT NULL,
FirstName NVARCHAR (30) NOT NULL,
LastName NVARCHAR (40) NOT NULL,
Title NVARCHAR (50) NOT NULL,
DeptID SMALLINT NOT NULL,
ManagerID SMALLINT NULL,
CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC),
CONSTRAINT FK_MyEmployees_ManagerID_EmployeeID FOREIGN KEY (ManagerID) REFERENCES dbo.MyEmployees (EmployeeID)
);
-- Populate the table with values.
INSERT INTO dbo.MyEmployees VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer', 16, NULL),
(273, N'Brian', N'Welcker', N'Vice President of Sales', 3, 1),
(274, N'Stephen', N'Jiang', N'North American Sales Manager', 3, 273),
(275, N'Michael', N'Blythe', N'Sales Representative', 3, 274),
(276, N'Linda', N'Mitchell', N'Sales Representative', 3, 274),
(285, N'Syed', N'Abbas', N'Pacific Sales Manager', 3, 273),
(286, N'Lynn', N'Tsoflias', N'Sales Representative', 3, 285),
(16, N'David', N'Bradley', N'Marketing Manager', 4, 273),
(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);
WITH DirectReports (ManagerID, EmployeeID, Title, EmployeeLevel) AS
(
SELECT ManagerID, EmployeeID, Title, 0 AS EmployeeLevel
FROM dbo.MyEmployees
WHERE ManagerID IS NULL
UNION ALL
SELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1
FROM dbo.MyEmployees AS e
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, EmployeeLevel
FROM DirectReports
ORDER BY ManagerID;
Rekurzív gyakori táblakifejezés használata két rekurziós szint megjelenítéséhez
Az alábbi példa a vezetőket és a nekik jelentett alkalmazottakat mutatja be. A visszaadott szintek száma kettőre korlátozódik.
WITH DirectReports (ManagerID, EmployeeID, Title, EmployeeLevel) AS
(
SELECT ManagerID, EmployeeID, Title, 0 AS EmployeeLevel
FROM dbo.MyEmployees
WHERE ManagerID IS NULL
UNION ALL
SELECT e.ManagerID, e.EmployeeID, e.Title, EmployeeLevel + 1
FROM dbo.MyEmployees AS e
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, EmployeeLevel
FROM DirectReports
WHERE EmployeeLevel <= 2;
Hierarchikus lista megjelenítése rekurzív gyakori táblakifejezéssel
Az alábbi példa hozzáadja a vezető és az alkalmazottak nevét, valamint a hozzájuk tartozó címeket. A vezetők és az alkalmazottak hierarchiáját az egyes szintek behúzásával is hangsúlyozzuk.
WITH DirectReports (Name, Title, EmployeeID, EmployeeLevel, Sort) AS
(
SELECT CONVERT (VARCHAR (255), e.FirstName + ' ' + e.LastName),
e.Title,
e.EmployeeID,
1,
CONVERT (VARCHAR (255), e.FirstName + ' ' + e.LastName)
FROM dbo.MyEmployees AS e
WHERE e.ManagerID IS NULL
UNION ALL
SELECT CONVERT (VARCHAR (255), REPLICATE('| ', EmployeeLevel) + e.FirstName + ' ' + e.LastName),
e.Title,
e.EmployeeID,
EmployeeLevel + 1,
CONVERT (VARCHAR (255), RTRIM(Sort) + '| ' + FirstName + ' ' + LastName)
FROM dbo.MyEmployees AS e
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
SELECT EmployeeID, Name, Title, EmployeeLevel
FROM DirectReports
ORDER BY Sort;
Utasítás lemondása a MAXRECURSION használatával
MAXRECURSION segítségével megakadályozhatja, hogy egy rosszul formázott rekurzív CTE végtelen hurokba lépjen. Az alábbi példa szándékosan létrehoz egy végtelen hurkot, és a MAXRECURSION tipp használatával a rekurziós szintek számát kettőre korlátozza.
--Creates an infinite loop
WITH cte (EmployeeID, ManagerID, Title) AS
(
SELECT EmployeeID, ManagerID, Title
FROM dbo.MyEmployees
WHERE ManagerID IS NOT NULL
UNION ALL
SELECT cte.EmployeeID, cte.ManagerID, cte.Title
FROM cte
INNER JOIN dbo.MyEmployees AS e
ON cte.ManagerID = e.EmployeeID
)
--Uses MAXRECURSION to limit the recursive levels to 2
SELECT EmployeeID, ManagerID, Title
FROM cte
OPTION (MAXRECURSION 2);
A kódolási hiba kijavítása után már nincs szükség MAXRECURSION. Az alábbi példa a javított kódot mutatja be.
WITH cte (EmployeeID, ManagerID, Title) AS
(
SELECT EmployeeID, ManagerID, Title
FROM dbo.MyEmployees
WHERE ManagerID IS NOT NULL
UNION ALL
SELECT e.EmployeeID, e.ManagerID, e.Title
FROM dbo.MyEmployees AS e
INNER JOIN cte
ON e.ManagerID = cte.EmployeeID
)
SELECT EmployeeID, ManagerID, Title
FROM cte;
E. Gyakori táblakifejezés használata rekurzív kapcsolat szelektív végiglépéséhez a SELECT utasításban
Az alábbi példa a kerékpár ProductAssemblyID = 800összeállításához szükséges termékszerelvények és összetevők hierarchiáját mutatja be.
USE AdventureWorks2022;
GO
WITH Parts (AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
(
SELECT b.ProductAssemblyID,
b.ComponentID,
b.PerAssemblyQty,
b.EndDate,
0 AS ComponentLevel
FROM Production.BillOfMaterials AS b
WHERE b.ProductAssemblyID = 800
AND b.EndDate IS NULL
UNION ALL
SELECT bom.ProductAssemblyID,
bom.ComponentID,
p.PerAssemblyQty,
bom.EndDate,
ComponentLevel + 1
FROM Production.BillOfMaterials AS bom
INNER JOIN Parts AS p
ON bom.ProductAssemblyID = p.ComponentID
AND bom.EndDate IS NULL
)
SELECT AssemblyID,
ComponentID,
Name,
PerAssemblyQty,
EndDate,
ComponentLevel
FROM Parts AS p
INNER JOIN Production.Product AS pr
ON p.ComponentID = pr.ProductID
ORDER BY ComponentLevel, AssemblyID, ComponentID;
F. Rekurzív CTE használata UPDATE utasításban
Az alábbi példa frissíti a PerAssemblyQty termék 'Road-550-W Yellow, 44' (ProductAssemblyID 800)összeállításához használt összes alkatrész értékét. A közös táblakifejezés a buildeléshez ProductAssemblyID 800 használt részek hierarchikus listáját adja vissza, valamint az ezen részek létrehozásához használt összetevőket stb. A rendszer csak a közös táblakifejezés által visszaadott sorokat módosítja.
USE AdventureWorks2022;
GO
WITH Parts (AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
(
SELECT b.ProductAssemblyID,
b.ComponentID,
b.PerAssemblyQty,
b.EndDate,
0 AS ComponentLevel
FROM Production.BillOfMaterials AS b
WHERE b.ProductAssemblyID = 800
AND b.EndDate IS NULL
UNION ALL
SELECT bom.ProductAssemblyID,
bom.ComponentID,
p.PerAssemblyQty,
bom.EndDate,
ComponentLevel + 1
FROM Production.BillOfMaterials AS bom
INNER JOIN Parts AS p
ON bom.ProductAssemblyID = p.ComponentID
AND bom.EndDate IS NULL
)
UPDATE Production.BillOfMaterials
SET PerAssemblyQty = c.PerAssemblyQty * 2
FROM Production.BillOfMaterials AS c
INNER JOIN Parts AS d
ON c.ProductAssemblyID = d.AssemblyID
WHERE d.ComponentLevel = 0;
H. Több horgony és rekurzív tag használata
Az alábbi példa több horgony- és rekurzív tagot használ egy adott személy összes elődjének visszaadásához. Létrejön egy tábla, és beszúrja az értékeket a rekurzív CTE által visszaadott családi genealógiához.
-- Genealogy table
IF OBJECT_ID('dbo.Person', 'U') IS NOT NULL
DROP TABLE dbo.Person;
GO
CREATE TABLE dbo.Person
(
ID INT,
Name VARCHAR (30),
Mother INT,
Father INT
);
GO
INSERT dbo.Person VALUES
(1, 'Sue', NULL, NULL),
(2, 'Ed', NULL, NULL),
(3, 'Emma', 1, 2),
(4, 'Jack', 1, 2),
(5, 'Jane', NULL, NULL),
(6, 'Bonnie', 5, 4),
(7, 'Bill', 5, 4);
GO
-- Create the recursive CTE to find all of Bonnie's ancestors.
WITH Generation (ID) AS
(
-- First anchor member returns Bonnie's mother.
SELECT Mother
FROM dbo.Person
WHERE Name = 'Bonnie'
UNION
-- Second anchor member returns Bonnie's father.
SELECT Father
FROM dbo.Person
WHERE Name = 'Bonnie'
UNION ALL
-- First recursive member returns male ancestors of the previous generation.
SELECT Person.Father
FROM Generation, Person
WHERE Generation.ID = Person.ID
UNION ALL
-- Second recursive member returns female ancestors of the previous generation.
SELECT Person.Mother
FROM Generation, dbo.Person
WHERE Generation.ID = Person.ID
)
SELECT Person.ID, Person.Name, Person.Mother, Person.Father
FROM Generation, dbo.Person
WHERE Generation.ID = Person.ID;
GO
I. Elemzési függvények használata rekurzív CTE-ben
Az alábbi példa egy olyan buktatót mutat be, amely akkor fordulhat elő, ha a CTE rekurzív részében analitikus vagy aggregátumfüggvényt használ.
DECLARE @t1 TABLE (itmID INT, itmIDComp INT);
INSERT @t1 VALUES (1, 10), (2, 10);
DECLARE @t2 TABLE (itmID INT, itmIDComp INT);
INSERT @t2 VALUES (3, 10), (4, 10);
WITH vw AS
(
SELECT itmIDComp, itmID FROM @t1
UNION ALL SELECT itmIDComp, itmID FROM @t2
),
r AS
(
SELECT t.itmID AS itmIDComp,
NULL AS itmID,
CAST (0 AS BIGINT) AS N,
1 AS Lvl
FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) AS t(itmID)
UNION ALL
SELECT t.itmIDComp,
t.itmID,
ROW_NUMBER() OVER (PARTITION BY t.itmIDComp ORDER BY t.itmIDComp, t.itmID) AS N,
Lvl + 1
FROM r
INNER JOIN vw AS t
ON t.itmID = r.itmIDComp
)
SELECT Lvl, N FROM r;
A következő eredmények a lekérdezés várt eredményei.
Lvl N
1 0
1 0
1 0
1 0
2 4
2 3
2 2
2 1
Az alábbi eredmények a lekérdezés tényleges eredményei.
Lvl N
1 0
1 0
1 0
1 0
2 1
2 1
2 1
2 1
NA CTE rekurzív részének minden egyes passzára 1 értéket ad vissza, mert a rendszer csak az adott rekurziós szinthez tartozó adathalmazt adja át.ROWNUMBER A lekérdezés rekurzív részének minden iterációjához csak egy sort ad át a ROWNUMBERrendszer.
Példák: Azure Synapse Analytics and Analytics Platform System (PDW)
J. Gyakori táblakifejezés használata CTAS-utasításban
Az alábbi példa egy új táblát hoz létre, amely az Adventure Works Cycles egyes értékesítési képviselőinek évi értékesítési rendeléseinek teljes számát tartalmazza.
USE AdventureWorks2022;
GO
CREATE TABLE SalesOrdersPerYear
WITH (DISTRIBUTION = HASH(SalesPersonID)) AS
-- Define the CTE expression name and column list.
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear) AS
-- Define the CTE query.
(
SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
)
-- Define the outer query referencing the CTE name.
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID
ORDER BY SalesPersonID, SalesYear;
GO
K. Közös táblakifejezés használata CETAS-utasításban
Az alábbi példa egy új külső táblát hoz létre, amely az Adventure Works Cycles egyes értékesítési képviselőinek évi értékesítési rendeléseinek teljes számát tartalmazza.
USE AdventureWorks2022;
GO
CREATE EXTERNAL TABLE SalesOrdersPerYear
WITH
(
LOCATION = 'hdfs://xxx.xxx.xxx.xxx:5000/files/Customer',
FORMAT_OPTIONS ( FIELD_TERMINATOR = '|' )
) AS
-- Define the CTE expression name and column list.
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear) AS
-- Define the CTE query.
(
SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear
FROM Sales.SalesOrderHeader
WHERE SalesPersonID IS NOT NULL
)
-- Define the outer query referencing the CTE name.
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear
FROM Sales_CTE
GROUP BY SalesYear, SalesPersonID
ORDER BY SalesPersonID, SalesYear;
GO
L. Több vesszővel tagolt CTE használata utasításban
Az alábbi példa két CTE-t mutat be egyetlen utasításban. A CTE-k nem ágyazhatók be (nincs rekurzió).
WITH CountDate (TotalCount, TableName) AS
(
SELECT COUNT(datekey), 'DimDate' FROM DimDate
),
CountCustomer (TotalAvg, TableName) AS
(
SELECT COUNT(CustomerKey), 'DimCustomer' FROM DimCustomer
)
SELECT TableName, TotalCount
FROM CountDate
UNION ALL
SELECT TableName, TotalAvg FROM CountCustomer;