CTE در SQL Server چیست؟ – راهنمای جامع همراه با مثال

CTE چیست؟
CTE یا Common Table Expression، مجموعه ای از نتایج موقتی است که در جایی ذخیره نشده و پس از پرس و جو های SQL حذف می شوند. CTE ابزاری محبوب در میان متخصصان پایگاه داده است که در یک دستور SQL ایجاد شده و سبب خوانایی بهتر و آسان تر شدن پرس و جو های پیچیده می شود.
استفاده از CTE در SQL (روش پایه)
نحوه کلی نوشتن CTE به صورت زیر است:WITH cte_name (column_1, column_2, column_3,...)AS (cte_query_definition)SELECT *FROM cte_name;
- WITH
عبارات CTE با کلمه With شروع شده و معرفی می شوند. - cte_name
نام عبارت که به عنوان یک شناسه معتبر شناخته می شود، باید با سایر نام های CTE های تعریف شده در عبارت WITH متفاوت باشد اما می تواند هم نام با View و نام جدول باشد. - cte_query_definition
این دستور از عبارتی به نام SELECT ایجاد شده است که نتیجه عملکرد آن، تولید یک CTE است. این دستور قابلیت تعریف CTE دیگری نداشته و حتماً باید دارای شرایط لازم برای ایجاد یک view را داشته باشد. اگر CTE_query_settings بیش از یک مورد باشد، پس به ترکیب query ها با عملگر هایی مانند UNION ALL و INTERSECT داریم.

1_ با استفاده از عبارت WITH
سرور SQL، درخواست های اطلاعاتی یا همان Query های فرعی را در WITH اجرا کرده و پس از استخراج داده، آن را در یک رابطه موقتی ذخیره می کند. در نهایت query اصلی برای ارائه نتیجه نهایی از همان رابطه موقتی استفاده می کند. مثال زیر، لیست محصولات طبق واحد های فروخته شده بازیابی کرده و نشان می دهد:WITH TopSoldProducts AS(SELECTp.ProductID,p.Name AS ProductName,SUM(sod.OrderQty) AS TotalQuantitySoldFROMProduction.Product pJOIN Sales.SalesOrderDetail sod ON p.ProductID = sod.ProductIDGROUP BYp.ProductID, p.Name)SELECTproductID,Product NameTotalQuantitySoldFROMTopSoldProducts;
نتیجه به این صورت به نمایش در می آید:

2_ با استفاده از چند CTE در یک query
در موقعیت هایی که برای رسیدن به نتیجه نیاز به بیش از یک CTE داریم، مجبور به نوشتن چند query جدا از هم نیستید زیرا SQL قابلیت ترکیب چند query با عملگر هایی که بالاتر به آن ها اشاره کردیم را ایجاد کرده است. موارد لازم برای ایجاد یک query با چند CTE به صورت زیر است:
- مجاز بودن یک query اصلی و کلمه WITH
- جدا سازی CTE با کمک کاما ( نیازی به استفاده از کاما قبل از query اصلی نیست.)
مثال زیر، ادامه کد بالاست اما با CTE های بیشتر:
WITH ProductCategoryCTE AS (SELECTProductCategoryID,Name AS CategoryNameFROMProduction.ProductCategory),ProductSubcategoryCTE AS (SELECTProductSubcategoryID,Name AS SubcategoryName,ProductCategoryIDFROMProduction.ProductSubcategory),ProductDetailCTE AS (SELECTp.ProductID,p.Name AS ProductName,p.ProductNumber,p. Color,p.ListPrice,ps.SubcategoryName,pc.CategoryNameFROMProduction.Product AS pLEFT JOINProductSubcategoryCTE AS ps ON p.ProductSubcategoryID = ps.ProductSubcategoryIDLEFT JOINProductCategoryCTE AS pc ON ps.ProductCategoryID = pc.ProductCategoryID)SELECTpd.ProductID,pd.ProductName,pd.ProductNumber,pd. Color,pd.ListPrice,pd.SubcategoryName,pd.CategoryNameFROMProductDetailCTE AS pdORDER BYpd.ProductID;
نتیجه به این صورت به نمایش در می آید:
استفاده از CTE در SQL (روش پیشرفته)
1_ CTE بازگشتی
CTE های بازگشتی، نتایج برگردانده شده توسط WITH را به صورت مکرر ارجاع می دهند تا به نتیجه مورد نظر برسد. Syntax کلی CTE بازگشتی به صورت زیر است:WITH RECURSIVE cte_name AS (cte_query_definition (the anchor member)UNION ALLcte_query_definition (the recursive member))SELECT *FROM cte_name;
- استفاده از WITH RECURSIVE
- دارای عضو لنگر (query اول)
- اتصال عضو لنگر به عضو بازگشتی با عملگر های UNION یا UNION ALL
WITH RecursiveCTE AS (SELECTTerritoryID,nameCountryRegionCode,[Group],1 AS LevelFROM Sales.SalesTerritoryWHERE TerritoryID = 1 -- Starting TerritoryIDUNION ALLSELECTT.TerritoryID,T. Name,T.CountryRegionCode,T. [Group],CTE.Level + 1 AS LevelFROM Sales.SalesTerritory TJOIN RecursiveCTE CTE ON T.TerritoryID = CTE.TerritoryIDWHERE CTE.Level < 100)SELECT * FROM RecursiveCTE;

2_ CTE تودرتو
CTE های تودرتو به این شکل هستند که می توانید از تعریف یک CTE در داخل تعریف یک CTE دیگر استفاده کنید. رایج ترین نوع استفاده از CTE ها تودرتو، محسابه میانگین و یا مقایسه های گروهی است. ساختار کلی یک CTE تودرتو به شکل زیر است:WITH cte_expression_1 as (cte_query_1),cte_expression_2 as (cte_query_2 -- (in the FROM clause refers to cte_expression_1))SELECT FROM cte_expression_2;
در مثال زیر، با استفاده از query های تودرتو گزارش هایی از اطلاعات فروش کل ارائه می شود:
WITH ProductSalesByCategory AS (SELECTpc.Name AS Category,psc.Name AS Subcategory,p.ProductID,p.Name AS ProductName,SUM(sod.LineTotal) AS TotalSalesFROMSales.SalesOrderDetail sodINNER JOINProduction.Product p ON sod.ProductID = p.ProductIDINNER JOINProduction.ProductSubcategory psc ON p.ProductSubcategoryID = psc.ProductSubcategoryIDINNER JOINProduction.ProductCategory pc ON psc.ProductCategoryID = pc.ProductCategoryIDGROUP BYpc.Name, psc.Name, p.ProductID, p.Name),CategoryTotalSales AS (SELECTCategoriesSUM(TotalSales) AS CategoryTotalFROMProductSalesByCategoryGROUP BYCategory)SELECTc.Category,c.CategoryTotal,p.ProductName,p.TotalSalesFROMProductSalesByCategory pJOINCategoryTotalSales c ON p.Category = c.CategoryORDER BYc.Category, p.ProductName;
نتیجه به این صورت به نمایش در می آید:

CTE و سایر ویژگی های SQL
در ادامه قرار است، سایر ویژگی های SQL و شباهت های آن ها با CTE را بررسی بررسی کنیم که به صورت زیر است: