Sql Server系列:通用表表达式CTE

1 CTE语法WITH关键字

  通用表表达式(Common Table Express, CTE),将派生表定义在查询的最前面。要使用CTE开始创建一个查询,可以使用WITH关键字。

  CTE语法:

WITH <expression_name> [(column_name [,...n])]
    AS
    ( CTE_query_definition)
    [, <another_expression>]
<query>

  首先为CTE提供一个名称,该名称类似于用于派生表的别名。然后可以提供CTE将返回的列名列表;如果CTE指定了它的所有返回列,则这是可选操作。最后,在圆括号中添加CTE查询的定义,最后添加使用CTE的主查询。

  WITH关键字之前的语句必须使用分号(;)结束。

  示例

WITH cte
AS
(
    SELECT * FROM [dbo].[Product]
)

SELECT [ProductID],[ProductCode],[ProductName],[UnitPrice] FROM cte

  连接查询示例

WITH ProductCTE([CategoryID], [ProductsCount])
AS
(
    SELECT [CategoryID],COUNT(1)
    FROM [dbo].[Product]
    GROUP BY [CategoryID]
)

SELECT c.[CategoryID],c.[CategoryName], cte.[ProductsCount]
FROM [dbo].[Category] c
INNER JOIN ProductCTE cte
    ON c.[CategoryID] = cte.[CategoryID]
ORDER BY cte.[ProductsCount]

2 使用多个CTE

  使用WITH开始语句可以定义多个CTE,不需要重复使用WITH关键字,每一个CTE可以使用在该语句中已经定义的任意CTE(作为其定义的一部分)。

WITH CategoryCTE
AS
(
    SELECT * FROM [dbo].[Category]
),ProductCTE
AS
(
    SELECT p.*,cte.[CategoryName] FROM [dbo].[Product] p
    INNER JOIN CategoryCTE cte
        ON p.[CategoryID] = cte.[CategoryID]
)

SELECT * FROM ProductCTE

3 递归CTE

  递归公用表表达式是在CTE内的语句中调用其自身的CTE。

  示例

WITH cte([CategoryID],[CategoryName],[ParentID],[Level])
AS
(
    -- 查询语句
    SELECT [CategoryID],[CategoryName],[ParentID],1 AS [Level] FROM [dbo].[Category]
    WHERE [ParentID] IS NULL
    UNION ALL
    -- 递归语句
    SELECT c.[CategoryID],c.[CategoryName],c.[ParentID], cte.[Level] + 1
    FROM [dbo].[Category] c
    INNER JOIN cte
        ON c.[CategoryID] = cte.[ParentID]
)

SELECT [CategoryID],[CategoryName],[ParentID],[Level] FROM cte

  限制递归层次

WITH cte([CategoryID],[CategoryName],[ParentID],[Level])
AS
(
    -- 查询语句
    SELECT [CategoryID],[CategoryName],[ParentID],1 AS [Level] FROM [dbo].[Category]
    WHERE [ParentID] IS NULL
    UNION ALL
    -- 递归语句
    SELECT c.[CategoryID],c.[CategoryName],c.[ParentID], cte.[Level] + 1
    FROM [dbo].[Category] c
    INNER JOIN cte
        ON c.[CategoryID] = cte.[ParentID]
)

SELECT [CategoryID],[CategoryName],[ParentID],[Level] FROM cte
OPTION(MAXRECURSION 2)

  Where过滤递归结果数据层次

WITH cte([CategoryID],[CategoryName],[ParentID],[Level])
AS
(
    -- 查询语句
    SELECT [CategoryID],[CategoryName],[ParentID],1 FROM [dbo].[Category]
    WHERE [ParentID] IS NULL
    UNION ALL
    -- 递归语句
    SELECT c.[CategoryID],c.[CategoryName],c.[ParentID], [Level] + 1
    FROM [dbo].[Category] c
    INNER JOIN cte
        ON c.[CategoryID] = cte.[ParentID]
)

SELECT [CategoryID],[CategoryName],[ParentID],[Level] FROM cte
WHERE cte.[Level] <= 3
posted @ 2015-04-27 23:06  libingql  阅读(8095)  评论(0编辑  收藏  举报