SQLServer中的CTE通用表表达式


1 2 CREATE VIEW vwMyView AS 3 SELECT 4 EmployeeID, COUNT(*) AS NumOrders, MAX(OrderDate) AS MaxDate 5 FROM Orders 6 GROUP BY EmployeeID 7 GO 8 9 SELECT 10 e.EmployeeID, oe.NumOrders, oe.MaxDate, e.ReportsTo AS ManagerID, 11 om.NumOrders, om.MaxDate 12 FROM 13 Employees AS e 14 INNER JOIN vwMyView AS oe ON e.EmployeeID = oe.EmployeeID 15 INNER JOIN vwMyView AS om ON e.ReportsTo = om.EmployeeID


1 SELECT 2 e.EmployeeID, oe.NumOrders, oe.MaxDate, e.ReportsTo AS ManagerID, 3 om.NumOrders, om.MaxDate 4 FROM 5 Employees AS e 6 INNER JOIN 7 (SELECT EmployeeID, COUNT(*), MAX(OrderDate) 8 FROM Orders 9 GROUP BY EmployeeID) AS oe(EmployeeID, NumOrders, MaxDate) 10 ON e.EmployeeID = oe.EmployeeID 11 LEFT JOIN 12 (SELECT EmployeeID, COUNT(*), MAX(OrderDate) 13 FROM Orders 14 GROUP BY EmployeeID) AS om(EmployeeID, NumOrders, MaxDate) 15 ON e.ReportsTo = om.EmployeeID
CTE 非常适用于此类情形,因为它提升了 T-SQL 的可读性(就像视图一样),而且能在同一个批处理后紧跟的查询中多次使用。当然,超出该范围它就不适用了。另外,CTE 是语言级别的构造,也就是说 SQL Server 不会在内部创建临时表或虚拟表。每次在紧随其后的查询中引用 CTE 的底层查询时都会调用它。


1 ;WITH EmpOrdersCTE (EmployeeID, NumOrders, MaxDate) AS 2 ( 3 SELECT EmployeeID, COUNT(*), MAX(OrderDate) 4 FROM Orders 5 GROUP BY EmployeeID 6 ) 7 8 SELECT 9 e.EmployeeID, oe.NumOrders, oe.MaxDate, 10 e.ReportsTo AS ManagerID, om.NumOrders, om.MaxDate 11 FROM 12 Employees AS e 13 INNER JOIN EmpOrdersCTE oe ON e.EmployeeID = oe.EmployeeID 14 LEFT JOIN EmpOrdersCTE om ON e.ReportsTo = om.EmployeeID

1 ;WITH myCTE (CustID, Co) AS 2 ( 3 SELECT CustomerID, CompanyName FROM Customers 4 ) 5 SELECT CustID, Co FROM myCTE

1 ;WITH myCTE (CustID, Co) AS 2 ( 3 SELECT CustomerID, CompanyName FROM Customers 4 ) 5 SELECT CompanyName FROM Customers WHERE CustomerID = 'ALFKI' 6 SELECT CustID, Co FROM myCTE

1 ;WITH myCTE AS 2 ( 3 SELECT c.CustomerID, c.CompanyName, o.OrderID, o.OrderDate 4 FROM Customers c 5 INNER JOIN Orders o ON c.CustomerID = o.CustomerID 6 ) 7 8 SELECT CustomerID, CompanyName, OrderID, OrderDate 9 FROM myCTE FOR XML AUTO
一旦定义了 CTE,跟随其后的首个查询便能多次引用它。这一功能在某个查询需要多次引用 CTE 时尤为有用。图 3 中的代码示例演示了查询如何引用 EmpOrdersCTE 两次,以便能获取员工和主管的信息。当需要多次引用同一行集时,这非常有用;引用 CTE 两次比复制该查询要简单得多。


;WITH EmpOrdersCTE (EmployeeID, NumOrders) AS ( SELECT EmployeeID, COUNT(*) FROM Orders GROUP BY EmployeeID ), MinMaxOrdersCTE (Mn, Mx, Diff) AS ( SELECT MIN(NumOrders), MAX(NumOrders), AVG(NumOrders) FROM EmpOrdersCTE ) SELECT Mn, Mx, Diff FROM MinMaxOrdersCTE
- 创建一个返回顶层(这是定位点成员)的查询。
- 编写一个递归查询(这是递归成员)。
- 通过 UNION 将第一个查询与递归查询结合起来。
- 确保存在没有行会被返回的情况(这是终止检查)。

1 ;WITH myRecursiveCTE(col1, col2, ... coln) AS 2 ( 3 -- 定位点成员 查询 4 UNION ALL 5 -- 递归成员 查询来自CTE的自身数据 6 )
-- DEFINE YOUR CTE HERE
SELECT * FROM EmpCTE
OPTION (MAXRECURSION 7)
- SELECT DISTINCT
- GROUP BY
- HAVING
- TOP
- LEFT/RIGHT OUTER JOIN


1 ;WITH EmpCTE(EmployeeID, EmployeeFirstName, 2 EmployeeLastName, MgrID, SalesLevel) 3 AS 4 ( 5 -- 定位点成员 6 SELECT EmployeeID, FirstName, LastName, ReportsTo, 0 7 FROM Employees 8 WHERE EmployeeID = 2 -- Start with the VP of Sales 9 10 UNION ALL 11 12 -- 递归成员 13 SELECT 14 e.EmployeeID, e.FirstName, e.LastName, e.ReportsTo, m.SalesLevel+1 15 FROM 16 Employees AS e 17 INNER JOIN EmpCTE m ON e.ReportsTo = m.EmployeeID 18 ) 19 20 -- 使用CTE 21 SELECT EmployeeID, EmployeeFirstName, EmployeeLastName, 22 MgrID, SalesLevel 23 FROM EmpCTE
成在管理,败在经验;嬴在选择,输在不学! 贵在坚持!
个人作品
BIMFace.SDK.NET
开源地址:https://gitee.com/NAlps/BIMFace.SDK
系列博客:https://www.cnblogs.com/SavionZhang/p/11424431.html
系列视频:https://www.cnblogs.com/SavionZhang/p/14258393.html
技术栈
1、AI、DeepSeek、MiniMax、通义千问
2、Visual Studio、.NET Core/.NET、MVC、Web API、RESTful API、gRPC、SignalR、Java、Python
3、jQuery、Vue.js、Bootstrap、ElementUI
4、数据库:分库分表、读写分离、SQLServer、MySQL、PostgreSQL、Redis、MongoDB、ElasticSearch、达梦DM、GaussDB、OpenGauss
5、架构:DDD、ABP、SpringBoot、jFinal
6、环境:跨平台、Windows、Linux
7、移动App:Android、IOS、HarmonyOS、微信小程序、钉钉、uni-app、MAUI
8、分布式、高并发、云原生、微服务、Docker、CI/CD、DevOps、K8S;Dapr、RabbitMQ、Kafka、RPC、Elasticsearch
欢迎关注作者头条号 张传宁IT讲堂,获取更多IT文章、视频等优质内容。
出处:www.cnblogs.com/SavionZhang
作者:张传宁 技术顾问、培训讲师、微软MCP、系统架构设计师、系统集成项目管理工程师、科技部创新工程师。
专注于企业级通用开发平台、工作流引擎、自动化项目(代码)生成器、SOA 、DDD、 云原生(Docker、微服务、DevOps、CI/CD);PDF、CAD、BIM 审图等研究与应用。
多次参与电子政务、图书教育、生产制造等企业级大型项目研发与管理工作。
熟悉中小企业软件开发过程:可行调研、需求分析、架构设计、编码测试、实施部署、项目管理。通过技术与管理帮助中小企业实现互联网转型升级全流程解决方案。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如有问题,可以通过邮件905442693@qq.com联系。共同交流、互相学习。
如果您觉得文章对您有帮助,请点击文章右下角【推荐】。您的鼓励是作者持续创作的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?