Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Şunlar için geçerlidir:SQL Server
Azure SQL Veritabanı
Azure SQL Yönetilen Örneği
Azure Synapse Analytics
Analiz Platformu Sistemi (PDW)
Microsoft Fabric'teki SQL analiz uç noktası
Microsoft Fabric'teki ambar
Microsoft Fabric'teki SQL veritabanı
Ortak tablo ifadesi (CTE) olarak bilinen geçici adlandırılmış bir sonuç kümesi belirtir. Bu, basit bir sorgudan türetilir ve tek SELECTbir , INSERT, UPDATE, MERGEveya DELETE deyiminin yürütme kapsamında tanımlanır. Bu yan tümce, tanımlayıcı CREATE VIEW deyiminin bir parçası olarak deyiminde SELECT de kullanılabilir. Ortak bir tablo ifadesi kendisine başvurular içerebilir. Bu, özyinelemeli ortak tablo ifadesi olarak adlandırılır.
Daha fazla bilgi için bkz. Ortak tablo ifadelerini kullanarak özyinelemeli sorgular.
Transact-SQL söz dizimi kuralları
Syntax
[ WITH <common_table_expression> [ , ...n ] ]
<common_table_expression>::=
expression_name [ ( column_name [ , ...n ] ) ]
AS
( CTE_query_definition )
Arguments
expression_name
Ortak tablo ifadesi için geçerli bir tanımlayıcı.
expression_name aynı WITH <common_table_expression> yan tümcede tanımlanan diğer ortak tablo ifadelerinden farklı olmalıdır, ancak expression_name temel tablo veya görünümün adıyla aynı olabilir. Sorgudaki expression_name başvurularında temel nesne değil ortak tablo ifadesi kullanılır.
column_name
Ortak tablo ifadesinde bir sütun adı belirtir. Tek bir CTE tanımı içinde yinelenen adlara izin verilmez. Belirtilen sütun adlarının sayısı , CTE_query_definition sonuç kümesindeki sütun sayısıyla eşleşmelidir. Sütun adları listesi, yalnızca sorgu tanımında elde edilen tüm sütunlar için ayrı adlar sağlandığında isteğe bağlıdır.
CTE_query_definition
Sonuç kümesi ortak tablo ifadesini dolduran bir SELECT deyimi belirtir.
SELECT
CTE_query_definition deyimi, bir CTE'nin başka bir CTE tanımlayamamaması dışında, görünüm oluşturma gereksinimleriyle aynı gereksinimleri karşılamalıdır. Daha fazla bilgi için Açıklamalar bölümüne ve CREATE VIEW bölümüne bakın.
Birden fazla CTE_query_definition tanımlanmışsa, sorgu tanımları şu küme işleçlerinden biri tarafından birleştirilmelidir: UNION ALL, UNION, EXCEPTveya INTERSECT.
Kullanım yönergeleri
Yaygın tablo ifadelerinden gelen sorgu sonuçları gerçekleşmez. Adlandırılmış sonuç kümesine yapılan her dış başvuru, tanımlı sorgunun yeniden yürütülmesini gerektirir. Adlandırılmış sonuç kümesine birden çok başvuru gerektiren sorgular için bunun yerine geçici bir nesne kullanmayı göz önünde bulundurun.
Ortak bir tablo ifadesinde saklı yordam yürütemezsiniz.
Özyinelemeli ve özyinelemeli olmayan CTE'ler hakkında kullanım yönergeleri için aşağıdaki bölümlere bakın.
- Özyinelemeli olmayan ortak tablo ifadeleri için yönergeler
- Özyinelemeli ortak tablo ifadeleri için yönergeler
Özyinelemeli olmayan ortak tablo ifadeleri için yönergeler
Note
Aşağıdaki yönergeler, özyinelemeli olmayan ortak tablo ifadeleri için geçerlidir. Özyinelemeli ortak tablo ifadelerine uygulanan yönergeler için bkz. Özyinelemeli ortak tablo ifadeleri için yönergeler.
CTE'yi, CTE sütunlarının bir kısmına veya SELECT tümüne başvuran tek INSERTbir , UPDATEMERGE, , DELETEveya deyimi takip etmelidir. CTE, görünümün tanımlayıcı CREATE VIEW deyiminin bir parçası olarak deyiminde SELECT de belirtilebilir.
Birden çok CTE sorgu tanımı, özyinelemeli olmayan bir CTE'de tanımlanabilir. Tanımlar şu küme işleçlerinden biri tarafından birleştirilmelidir: UNION ALL, UNION, INTERSECTveya EXCEPT.
CTE, aynı WITH yan tümcede kendisine ve daha önce tanımlanmış CTE'lere başvurabilir. İleriye başvuruya izin verilmez.
CTE'de birden WITH fazla yan tümce belirtilmesine izin verilmez. Örneğin, bir CTE_query_definition bir alt sorgu içeriyorsa, bu alt sorgu başka bir CTE'yi tanımlayan iç içe WITH bir yan tümce içeremez.
Microsoft Fabric'te iç içe yerleştirilmiş CTE'ler hakkında daha fazla bilgi için bkz. Doku veri ambarında İç İçe Ortak Tablo İfadesi (CTE) (Transact-SQL).
aşağıdaki yan tümceler CTE_query_definition kullanılamaz:
-
ORDER BY(orTOPyan tümcesi belirtildiği durumlarOFFSET/FETCHdışında) INTO-
OPTIONsorgu ipuçlarını içeren yan tümce 1 FOR BROWSE
1 Yan OPTION tümcesi bir CTE tanımı içinde kullanılamaz. Yalnızca en SELECT dıştaki deyimde kullanılabilir.
Bir toplu iş parçası olan bir deyimde bir CTE kullanıldığında, önce deyimi noktalı virgül tarafından takip edilmelidir.
bir Imleç tanımlamak için CTE'ye başvuran bir sorgu kullanılabilir.
Uzak sunuculardaki tablolara CTE'de başvurulabilir.
CTE yürütürken, CTE'ye başvuran tüm ipuçları, CTE temel tablolarına eriştiğinde bulunan diğer ipuçlarıyla çakışabilir ve sorgulardaki görünümlere başvuran ipuçlarıyla aynı şekilde. Bu durum oluştuğunda sorgu bir hata döndürür.
Özyinelemeli ortak tablo ifadeleri için yönergeler
Note
Aşağıdaki yönergeler özyinelemeli bir ortak tablo ifadesi tanımlamak için geçerlidir. Özyinelemeli olmayan CTE'ler için geçerli olan yönergeler için bkz. Özyinelemeli olmayan ortak tablo ifadeleri için yönergeler.
Özyinelemeli CTE tanımı en az iki CTE sorgu tanımı içermelidir: bir tutturucu üye ve özyinelemeli üye. Birden çok tutturucu üye ve özyinelemeli üye tanımlanabilir; ancak, tüm tutturucu üye sorgu tanımları ilk özyinelemeli üye tanımından önce yerleştirilmelidir. Tüm CTE sorgu tanımları, CTE'nin kendisine başvurmadıkları sürece bağlayıcı üyeleridir.
Tutturucu üyeleri şu küme işleçlerinden biri tarafından birleştirilmelidir: UNION ALL, UNION, INTERSECTveya EXCEPT.
UNION ALL , son tutturucu üye ile ilk özyinelemeli üye arasında ve birden çok özyinelemeli üyeyi birleştirirken izin verilen tek küme işlecidir.
Tutturucudaki ve özyinelemeli üyelerdeki sütun sayısı aynı olmalıdır.
Özyinelemeli üyedeki bir sütunun veri türü, bağlayıcı üyedeki ilgili sütunun veri türüyle aynı olmalıdır.
Özyinelemeli FROM bir üyenin yan tümcesi CTE expression_name yalnızca bir kez başvurmalıdır.
Özyinelemeli üyenin CTE_query_definition aşağıdaki öğelere izin verilmez:
SELECT DISTINCTGROUP BY-
PIVOT1 HAVING- Skaler agregasyon
TOP-
LEFT,RIGHT,OUTER JOIN(INNER JOINizin verilir) - Subqueries
- bir CTE_query_definition içindeki CTE'ye özyinelemeli başvuruya uygulanan ipucu.
1 Veritabanı uyumluluk düzeyi 110 veya daha yüksek olduğunda. Bkz . SQL Server 2016'da Veritabanı Altyapısı özelliklerinde hataya neden olan değişiklikler.
Aşağıdaki yönergeler özyinelemeli bir ortak tablo ifadesi kullanmak için geçerlidir:
Özyinelemeli CTE tarafından döndürülen tüm sütunlar, katılan
SELECTdeyimler tarafından döndürülen sütunların null atanabilirliğine bakılmaksızın null atanabilir.Yanlış oluşturulmuş özyinelemeli bir CTE sonsuz döngüye neden olabilir. Örneğin, özyinelemeli üye sorgu tanımı hem üst hem de alt sütunlar için aynı değerleri döndürürse, sonsuz bir döngü oluşturulur. Sonsuz döngünün önüne geçmek için, , , veya
MAXRECURSIONdeyiminin yan tümcesinde ve arasında032767OPTIONbir ipucu ve bir değer kullanarakINSERTbelirli bir deyim için izin verilen özyineleme düzeylerininUPDATEDELETEsayısını sınırlayabilirsinizSELECT. Bu, döngü oluşturan kod sorununu çözene kadar deyiminin yürütülmesini denetlemenizi sağlar. Sunucu genelinde varsayılan değer 100'dür. 0 belirtildiğinde hiçbir sınır uygulanmaz. Deyim başına yalnızca birMAXRECURSIONdeğer belirtilebilir. Daha fazla bilgi için bkz. Sorgu ipuçları.Özyinelemeli ortak tablo ifadesi içeren bir görünüm, verileri güncelleştirmek için kullanılamaz.
İmleçler, CTA'lar kullanılarak sorgularda tanımlanabilir. CTE, imlecin sonuç kümesini tanımlayan select_statement bağımsız değişkenidir. Özyinelemeli CTE'ler için yalnızca hızlı ileriye doğru ve statik (anlık görüntü) imleçlere izin verilir. Özyinelemeli bir CTE'de başka bir imleç türü belirtilirse, imleç türü statik olarak dönüştürülür.
Uzak sunuculardaki tablolara CTE'de başvurulabilir. CTE'nin özyinelemeli üyesinde uzak sunucuya başvurulursa, her uzak tablo için bir biriktirici oluşturulur, böylece tablolara yerel olarak tekrar tekrar erişilebilir. Bu bir CTE sorgusuysa, sorgu planında Dizin Biriktiricisi/Gecikmeli Biriktiriciler görüntülenir ve ek
WITH STACKkoşula sahip olur. Bu, doğru özyinelemesi onaylamanın bir yoludur.CTE'nin özyinelemeli bölümündeki analiz ve toplama işlevleri, CTE kümesine değil, geçerli özyineleme düzeyi için kümeye uygulanır. CTE'nin özyinelemeli bölümüne geçirilen veri kümesinin tamamına değil, yalnızca geçerli özyineleme düzeyine göre geçirilen verilerin alt kümesinde çalışma gibi
ROW_NUMBERişlevler. Daha fazla bilgi için bkz. örnek I. Aşağıdaki özyinelemeli CTE'de analitik işlevleri kullanma.
Azure Synapse Analytics ve Analytics Platform Sistemi'nde (PDW) yaygın tablo ifadeleri
Azure Synapse Analytics ve Analytics Platform Sistemi'nde (PDW) CTE'lerin geçerli uygulaması aşağıdaki özelliklere ve gereksinimlere sahiptir:
Bir deyimde
SELECTCTE belirtilebilir.Bir deyimde
CREATE VIEWCTE belirtilebilir.CTE bir
CREATE TABLE AS SELECT(CTAS) deyiminde belirtilebilir.CTE bir
CREATE REMOTE TABLE AS SELECT(CRTAS) deyiminde belirtilebilir.CTE bir
CREATE EXTERNAL TABLE AS SELECT(CETAS) deyiminde belirtilebilir.CTE'den uzak bir tabloya başvurulabilir.
CTE'den dış tabloya başvurulabilir.
CTE'de birden çok CTE sorgu tanımı tanımlanabilir.
CTE'yi , ,
SELECT,INSERT,UPDATEveyaDELETEdeyimleri takipMERGEedebilir.Kendisine başvurular içeren ortak tablo ifadesi (özyinelemeli bir ortak tablo ifadesi) desteklenmez.
CTE'de birden
WITHfazla yan tümce belirtilmesine izin verilmez. Örneğin, bir CTE sorgu tanımı bir alt sorgu içeriyorsa, bu alt sorgu başka bir CTE'yi tanımlayan iç içeWITHbir yan tümce içeremez.Yan
ORDER BYtümce, bir yan tümce belirtildiği durumlar dışındaTOPkullanılamaz.Bir toplu iş parçası olan bir deyimde bir CTE kullanıldığında, önce deyimi noktalı virgül tarafından takip edilmelidir.
tarafından
sp_preparehazırlanan deyimlerde kullanıldığında, CTA'lar APS PDW'deki diğerSELECTdeyimlerle aynı şekilde davranır. Ancak, CTA'lar tarafındansp_preparehazırlanan CETAS'ın bir parçası olarak kullanılıyorsa, bağlamanın içinsp_prepareuygulanma şekli nedeniyle davranış SQL Server'dan ve diğer APS PDW deyimlerinden ertelenebilir. Bu, CTE'ye başvuruda bulunursa CTE'de bulunmayan yanlış bir sütun kullanıyorsaSELECT,sp_preparehata algılanmadan geçer, ancak bunun yerine hata oluşursp_execute.
Examples
A. Ortak tablo ifadesi oluşturma
Aşağıdaki örnekte Adventure Works Cycles'taki her satış temsilcisi için yıllık toplam satış siparişi sayısı gösterilmektedir.
-- 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. Sayıları ve rapor ortalamalarını sınırlamak için ortak bir tablo ifadesi kullanma
Aşağıdaki örnekte, satış temsilcileri için tüm yılların ortalama satış siparişi sayısı gösterilmektedir.
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. Tek bir sorguda birden çok CTE tanımı kullanma
Aşağıdaki örnekte, tek bir sorguda birden fazla CTE'nin nasıl tanımlanacağı gösterilmektedir. CTE sorgu tanımlarını ayırmak için virgül kullanılır.
FORMAT Parasal tutarları para birimi biçiminde görüntülemek için kullanılan işlev, SQL Server 2012'de (11.x) kullanıma sunulmuştur.
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;
Kısmi bir sonuç kümesi aşağıdadır.
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. Birden çok özyineleme düzeyini görüntülemek için özyinelemeli ortak tablo ifadesi kullanma
Aşağıdaki örnekte yöneticilerin ve onlara rapor veren çalışanların hiyerarşik listesi gösterilmektedir. Örnek, tabloyu oluşturup doldurarak dbo.MyEmployees başlar.
-- 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;
özyinelemenin iki düzeyini görüntülemek için özyinelemeli ortak tablo ifadesi kullanma
Aşağıdaki örnek, yöneticileri ve onlara rapor eden çalışanları gösterir. Döndürülen düzey sayısı iki ile sınırlıdır.
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;
Hiyerarşik liste görüntülemek için özyinelemeli ortak tablo ifadesi kullanma
Aşağıdaki örnek, yönetici ve çalışanların adlarını ve ilgili başlıklarını ekler. Yöneticilerin ve çalışanların hiyerarşisi, her düzeyin girintilenmesiyle de vurgulanır.
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;
Bir deyimi iptal etmek için MAXRECURSION kullanma
MAXRECURSION düşük biçimlendirilmiş özyinelemeli bir CTE'nin sonsuz döngüye girmesini önlemek için kullanılabilir. Aşağıdaki örnek kasıtlı olarak sonsuz bir döngü oluşturur ve özyineleme düzeylerinin sayısını iki ile sınırlamak için MAXRECURSION ipucunu kullanır.
--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);
Kodlama hatası düzeltildikten sonra MAXRECURSION artık gerekli değildir. Aşağıdaki örnekte düzeltilen kod gösterilmektedir.
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. SELECT deyimindeki özyinelemeli ilişkide seçmeli olarak adım adım ilerletmek için ortak tablo ifadesi kullanma
Aşağıdaki örnekte için bisiklet oluşturmak için ProductAssemblyID = 800gereken ürün derlemeleri ve bileşenleri hiyerarşisi gösterilmektedir.
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. UPDATE deyiminde özyinelemeli CTE kullanma
Aşağıdaki örnek, ürününü PerAssemblyQtyderlemek 'Road-550-W Yellow, 44' (ProductAssemblyID 800) için kullanılan tüm parçaların değerini güncelleştirir. Ortak tablo ifadesi, derlemek ProductAssemblyID 800 için kullanılan parçaların hiyerarşik bir listesini ve bu parçaları oluşturmak için kullanılan bileşenleri vb. döndürür. Yalnızca ortak tablo ifadesi tarafından döndürülen satırlar değiştirilir.
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. Birden çok tutturucu ve özyinelemeli üye kullanma
Aşağıdaki örnek, belirtilen bir kişinin tüm atalarını döndürmek için birden çok tutturucu ve özyinelemeli üye kullanır. Özyinelemeli CTE tarafından döndürülen aile soy ağacını oluşturmak için bir tablo oluşturulur ve değerler eklenir.
-- 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. Özyinelemeli CTE'de analitik işlevleri kullanma
Aşağıdaki örnekte, CTE'nin özyinelemeli bölümünde analitik veya toplama işlevi kullanılırken oluşabilecek bir tuzak gösterilmektedir.
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şağıdaki sonuçlar sorgu için beklenen sonuçlardır.
Lvl N
1 0
1 0
1 0
1 0
2 4
2 3
2 2
2 1
Aşağıdaki sonuçlar sorgunun gerçek sonuçlarıdır.
Lvl N
1 0
1 0
1 0
1 0
2 1
2 1
2 1
2 1
N CTE'nin özyinelemeli bölümünün her geçişi için 1 döndürür çünkü bu özyineleme düzeyine ait verilerin yalnızca alt kümesi öğesine ROWNUMBERgeçirilir. Sorgunun özyinelemeli bölümünün yinelemelerinin her biri için öğesine yalnızca bir satır geçirilir ROWNUMBER.
Örnekler: Azure Synapse Analytics ve Analytics Platform Sistemi (PDW)
J. CTAS deyimi içinde ortak tablo ifadesi kullanma
Aşağıdaki örnek, Adventure Works Cycles'taki her satış temsilcisi için yıllık toplam satış siparişi sayısını içeren yeni bir tablo oluşturur.
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. CETAS deyimi içinde ortak tablo ifadesi kullanma
Aşağıdaki örnek, Adventure Works Cycles'taki her satış temsilcisi için yıllık toplam satış siparişi sayısını içeren yeni bir dış tablo oluşturur.
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. Deyimde birden çok virgülle ayrılmış CTS kullanma
Aşağıdaki örnek, tek bir deyimde iki CTA'nın dahil olduğunu gösterir. CTE'ler iç içe yerleştirilemiyor (özyineleme yok).
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;