-- CTE, definition
with C1(orderyear, custid) as (
select year(orderdate), CustomerID
from SalesLT.SalesOrderHeader
),
C2 as (
select orderyear, count(DISTINCT custid) as numcusts
from C1
group by orderyear
)
select orderyear, numcusts
from C2
where numcusts > 30;
CTE的多引用
相对于派生表,因为CTE先于from子句定义,因此可以引用同一CTE的多个实例。
避免了像派生表那样需要维护多个子查询的副本
-- CTE, multi-reference
with YearlyCount as (
select YEAR(orderdate) as orderyear
, COUNT(distinct customerID) as numcusts
from SalesLT.SalesOrderHeader
group by YEAR(OrderDate)
)
select Cur.orderyear
, Cur.numcusts as CurNumCusts
, Prv.numcusts as PrvNumCusts
, Cur.numcusts - Prv.numcusts as Growth
from YearlyCount as Cur
left join YearlyCount as Prv
on Cur.orderyear = Prv.orderyear + 1 CTE的递归
-- CTE, Recursive
WITH CategoryCTE([ParentProductCategoryID], [ProductCategoryID], [Name]) AS (
-- anchor member, executed only in the beginning
SELECT [ParentProductCategoryID], [ProductCategoryID], [Name]
FROM SalesLT.ProductCategory
WHERE ParentProductCategoryID IS NULL
UNION ALL -- to union all recursive query results
-- recursive member
SELECT C.[ParentProductCategoryID], C.[ProductCategoryID], C.[Name]
FROM SalesLT.ProductCategory AS C
INNER JOIN CategoryCTE AS BC
ON BC.ProductCategoryID = C.ParentProductCategoryID
)
SELECT PC.[Name] AS [ParentProductCategoryName]
, CCTE.[Name] as [ProductCategoryName]
, CCTE.[ProductCategoryID]
FROM CategoryCTE AS CCTE
JOIN SalesLT.ProductCategory AS PC
ON PC.[ProductCategoryID] = CCTE.[ParentProductCategoryID] 视图属性和选项
ALTER VIEW [SalesLT].[vEnProduct]
WITH SCHEMABINDING, encryption -- view attributes
AS
SELECT p.[ProductID]
,p.[Name]
,pmx.[Culture]
,pd.[Description]
FROM [SalesLT].[Product] p
INNER JOIN [SalesLT].[ProductModelProductDescription] pmx
ON p.[ProductModelID] = pmx.[ProductModelID]
INNER JOIN [SalesLT].[ProductDescription] pd
ON pmx.[ProductDescriptionID] = pd.[ProductDescriptionID]
WHERE pmx.Culture = 'en' -- this view only contains products for 'en'
WITH CHECK OPTION;
GO
-- Error sample: conflict with CHECK OPTION
-- Can't be changed to other culture other than 'en'
update P
set P.Culture = 'zh'
from SalesLT.vEnProduct as P
-- You can't insert a record without 'en' Culture tagged 内联表值函数(参数化视图)
除了支持输入参数以外,其他方面与视图类似,下边是一个例子:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ufnGetCustomerInformation]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
DROP FUNCTION [dbo].[ufnGetCustomerInformation]
GO
CREATE FUNCTION [dbo].[ufnGetCustomerInformation]
(@CustomerID int) RETURNS TABLE
AS
RETURN (
SELECT
CustomerID,
FirstName,
LastName
FROM [SalesLT].[Customer]
WHERE [CustomerID] = @CustomerID
-- Get the first 3 orders of each customer
select C.CustomerID
, A.SalesOrderID
, A.OrderDate
from SalesLT.Customer as C
outer apply (
select top(3) SalesOrderID, OrderDate
from SalesLT.SalesOrderHeader as O
where O.CustomerID = C.CustomerID
order by OrderDate desc, SalesOrderID desc
) as A
order by C.CustomerID