SQL2005/2008中的CTE应用--递归查询

 


微软从SQl2005起引入了CTE(Common Table Expression)以强化T-SQL。这是一个类似于非持久视图的好东东。

按照MSDN介绍

1、公用表表达式 (CTE) 可以认为是在单个 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句的执行范围内定义的临时结果集 。CTE 与派生表类似,具体表现在不存储为对象,并且只在查询期间有效 。与派生表的不同之处在于,CTE 可自引用,还可在同一查询中引用多次 。

CTE 可用于:

创建递归查询。有关详细信息,请参阅使用公用表表达式的递归查询 。 
在不需要常规使用视图时替换视图,也就是说,不必将定义存储在元数据中。 
启用按从标量嵌套 select 语句派生的列进行分组,或者按不确定性函数或有外部访问的函数进行分组。 
在同一语句中多次引用生成的表。 
使用 CTE 可以获得提高可读性和轻松维护复杂查询的优点。查询可以分为单独块、简单块、逻辑生成块。之后,这些简单块可用于生成更复杂的临时 CTE,直到生成最终结果集。可以在用户定义的例程(如函数、存储过程触发器或视图)中定义 CTE。

2、公用表表达式 (CTE) 具有一个重要的优点,那就是能够引用其自身,从而创建递归 CTE 。递归 CTE 是一个重复执行初始 CTE 以返回数据子集直到获取完整结果集的公用表表达式。当某个查询引用递归 CTE 时,它即被称为递归查询 。递归查询通常用于返回分层数据,例如:显示某个组织图中的雇员或物料清单方案(其中父级产品有一个或多个组件,而那些组件可能还有子组件,或者是其他父级产品的组件)中的数据。

递归 CTE 可以极大地简化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 语句中运行递归查询所需的代码。在 SQL Server 的早期版本中,递归查询通常需要使用临时表、游标和逻辑来控制递归步骤流。有关公用表表达式的详细信息,请参阅使用公用表表达式 。

 这里举例说明如下:


IF OBJECT_ID('Cate') IS NOT NULL 
DROP TABLE CATE

GO

CREATE TABLE Cate
(
ID INT IDENTITY(1,1) PRIMARY KEY,
[C_Name] NVARCHAR(50),
[C_Level] [int] NOT NULL,
[C_Code] NVARCHAR(255) NULL,
[C_Parent] [int] NOT NULL
)

GO
 
INSERT INTO [Cate] VALUES('分类1',1,'0',0 )  
INSERT INTO [Cate] VALUES('分类2',1,'0',0 )  
INSERT INTO [Cate] VALUES('分类3',1,'0',0 )  
INSERT INTO [Cate] VALUES('分类4',1,'0',0 )  
INSERT INTO [Cate] VALUES('分类5',2,'1/',1 )  
INSERT INTO [Cate] VALUES('分类6',2,'1/',1 )  
INSERT INTO [Cate] VALUES('分类7',2,'2/',2 )  
INSERT INTO [Cate] VALUES('分类8',2,'2/',2 )  
INSERT INTO [Cate] VALUES('分类9',3,'1/5',5 )  
INSERT INTO [Cate] VALUES('分类10',3,'1/6',6 )  
INSERT INTO [Cate] VALUES('分类11',4,'1/5/9',9 )  
INSERT INTO [Cate] VALUES('分类12',4,'1/5/9/11',10 )  


GO
--WCT第一种方法
;WITH CTETBL  AS
(
SELECT ID,[C_Name],C_Parent,[C_Code] FROM [Cate] WHERE ID=1 UNION ALL

SELECT A.ID,A.[C_Name],A.C_Parent,A.[C_Code]  FROM 
CTETBL B  INNER JOIN 
[Cate] A
ON B.ID=A.[C_Parent]

)
SELECT * FROM CTETBL order by id 

--WCT第二种方法,(在查询的时候加上级别,Sublevel字段表现的淋漓尽致)
;WITH CTETBL2(C_Name, ID, C_Code,C_Parent,Sublevel) AS
(SELECT C_Name, ID, C_Code,C_Parent,0  FROM [Cate] WHERE ID =1
UNION ALL
SELECT p.C_Name, p.ID, p.C_Code,p.C_parent,Sublevel+1
 FROM [Cate]  P  INNER JOIN
 CTETBL2 A ON A.ID = P.C_Parent
)
SELECT * FROM CTETBL2  
 
GO

--如果数据库表结构设计的好.
SELECT ID,[C_Name],C_Parent,[C_Code],
ISNULL((SELECT TOP 1 C_Name FROM [Cate] A WHERE A.ID=S.C_Parent ),'') PName
FROM [Cate] S 
WHERE C_Code like '1/%'

GO

GO

这个应用示例重在简化业务逻辑 ,即便是性能不佳,但对临时表\表变量\游标等传统处理方式是一种业务层次上的简化或者说是优化


部分内容转自:http://www.jzxue.com/shujuku/mssqlserver/200910/24-3001.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值