SELECT speaker, track, score,
CASE NTILE(3) OVER(ORDER BY score DESC)
WHEN 1 THEN ''High''
WHEN 2 THEN ''Medium''
WHEN 3 THEN ''Low''
END AS scorecategory
FROM SpeakerStats
ORDER BY track, speaker
以下为结果集:
speaker track score scorecategory
---------- ---------- ----------- -------------
Kevin DB 7 Medium
Mike DB 8 Medium
Suzanne DB 9 High
Jessica Dev 9 High
Joe Dev 6 Low
Robert Dev 6 Low
Ron Dev 9 High
Brian Sys 7 Medium
Dan Sys 3 Low
Kathy Sys 8 High
Michele Sys 8 Medium
递归查询和常见表表达式
本节探讨递归 CTE 表达式的细节,并且将它们作为常见问题的解决方案加以应用,以大大简化传统的方法。
常见表表达式
常见表表达式 (CTE) 是一个可以由定义语句引用的临时命名的结果集。在它们的简单形式中,您可以将 CTE 视为更类似于非持续性类型视图的派生表的改进版本。在查询的 FROM 子句中引用 CTE 的方式类似于引用派生表和视图的方式。只须定义 CTE 一次,即可在查询中多次引用它。在 CTE 的定义中,可以引用在同一批处理中定义的变量。您甚至可以在 INSERT、UPDATE、DELETE 和 CREATE VIEW 语句中以与使用视图类似的方式使用 CTE。但是,CTE 的真正威力在于它们的递归功能,即 CTE 可以包含对它们自身的引用。在本文中,首先描述简单形式的 CTE,稍后再描述它们的递归形式。本文讨论通过 CTE 进行的 SELECT 查询。
当您希望像引用表一样引用查询结果,但是不希望在数据库中创建持久性视图时,可以使用派生表。但是,派生表具有 CTE 中所不具有的限制:您无法只在查询中定义派生表一次然后多次使用它。相反,您必须在同一查询中定义多个派生表。但是,您可以定义 CTE 一次并在查询中多次使用它,而无须在数据库中持续保存它。
在提供 CTE 的实际示例之前,首先将 CTE 的基本语法与派生表和视图进行比较。以下是视图、派生表和 CTE 内部的查询的一般形式:
视图
CREATE VIEW <view_name>(<column_aliases>)
AS
<view_query>
GO
SELECT *
FROM <view_name>
派生表
SELECT *
FROM (<derived_table_query>) AS <derived_table_alias>(<column_aliases>)
CTE
WITH <cte_alias>(<column_aliases>)
AS
(
<cte_query>
)
SELECT *
FROM <cte_alias>
在关键字 WITH 之后,为 CTE 提供一个别名,并且为它的结果列提供一个可选的别名列表;编写 CTE 的主体;然后从外部查询中引用它。
请注意,如果 CTE 的 WITH 子句不是批处理中的第一个语句,则您应当通过在它前面放置一个分号 (;) 来将其与前面的语句分隔开。分号用来避免与 WITH 子句的其他用法(例如,用于表提示)混淆。尽管您可能会发现并非在所有情况下都需要包含分号,但还是建议您始终如一地使用它。
作为一个实际示例,请考虑 AdventureWorks 数据库中的 HumanResources.Employee 和 Purchasing.PurchaseOrderHeader 表。每个雇员都向 ManagerID 列中指定的经理汇报。Employee 表中的每个雇员都可能在 PurchaseOrderHeader 表中具有相关的定单。假设您希望返回每个雇员的定单数量和最后定单日期,并且在同一行中返回经理的类似详细信息。以下示例显示了如何使用视图、派生