我们编写CTE sql,如下所示
WITH yourCTE AS
(
SELECT .... FROM :... WHERE.....
) SELECT * FROM yourCTE
将sql放入块中会有什么好处。我认为如果我们将复杂的sql放入块中,那么我们就可以编写像SELECT * FROM yourCTE
这样的sql。好像我正在访问视图。
在性能方面使用CTE的附加优势是什么。请讨论。感谢
答案 0 :(得分:15)
在许多情况下,CTE非常有用:
递归查询,就像走上一个层次结构树一样 - 没有CTE就非常棘手和繁琐(见here for a sample of a recursive CTE)
只要您想使用其中一个排名函数,例如ROW_NUMBER()
,RANK()
,NTILE()
等等(请参阅{{3} })
一般情况下,您需要首先根据某些条件选择几行/列,然后对这些行执行某些操作,例如:更新表,删除重复项等。
我经常使用CTE的一种情况是删除除给定数据集的最新行之外的所有行,例如如果你有客户和他们的订单有1:n的关系,并且你想要删除除最近订单之外的所有订单(基于OrderDate
),对于每个客户,在SQL中执行此操作会非常繁琐CTE。
使用CTE和排名功能,这是轻而易举的事:
;WITH CustomerOrders AS
(
SELECT
c.CustomerID, o.OrderID,
ROW_NUMBER() OVER(PARTITION BY c.CustomerID ORDER BY o.OrderDate DESC) AS 'RowN'
FROM
dbo.Customer c
INNER JOIN
dbo.Orders o ON o.CustomerID = c.CustomerID
)
DELETE FROM
dbo.Orders
FROM
CustomerOrders co
WHERE
dbo.Orders.OrderID = co.OrderID
AND co.RowN > 1
使用此功能,您可以创建一个按CustomerID
分区的“内嵌视图”(例如,每个客户从1开始获取rownumbers),按OrderDate DESC
排序(最新订单优先)。对于每个客户,最新的,最近的订单有RowN = 1
,因此您可以轻松地删除所有其他行,并且您已经完成了您想要做的事情 - 带有CTE的小菜一碟 - 没有它的杂乱代码。 ..
答案 1 :(得分:3)
This MSDN article描述的最好。最重要的是,如果您已经从视图中选择数据,则不必将其包装在CTE中,然后从CTE中选择。我不认为CTE和视图之间存在很大差异(表现明智)。至少不符合我的经验(我最近一直在处理一些容纳大量记录的复杂数据库结构)。但是,CTE非常适合递归选择。
另一方面,如果您在查询中多次选择连接数据的相同子集并且没有为其定义视图,则CTE可能是有益的。如果您只是为一个查询加入数据然后将其包装在CTE中,我认为这太过分了。即使您没有使用CTE,查询路径仍会被缓存...
答案 2 :(得分:0)
答案 3 :(得分:-3)
晚上好朋友。今天我们将了解Common table表达式,它是SQL Server 2005中引入的新功能,也可以在以后的版本中使用。
公用表表达式: - 公用表表达式可以定义为临时结果集,换句话说,它可以替代SQL Server中的视图。公用表表达式仅在定义它的批处理语句中有效,不能在其他会话中使用。
声明CTE的语法(公用表表达式): -
with [Name of CTE]
as
(
Body of common table expression
)
让我们举一个例子: -
CREATE TABLE Employee([EID] [int] IDENTITY(10,5) NOT NULL,[Name] [varchar](50) NULL)
insert into Employee(Name) values('Neeraj')
insert into Employee(Name) values('dheeraj')
insert into Employee(Name) values('shayam')
insert into Employee(Name) values('vikas')
insert into Employee(Name) values('raj')
CREATE TABLE DEPT(EID INT,DEPTNAME VARCHAR(100))
insert into dept values(10,'IT')
insert into dept values(15,'Finance')
insert into dept values(20,'Admin')
insert into dept values(25,'HR')
insert into dept values(10,'Payroll')
我创建了两个表employee和Dept,并在每个表中插入了5行。现在我想加入这些表并创建一个临时结果集以进一步使用它。
With CTE_Example(EID,Name,DeptName)
as
(
select Employee.EID,Name,DeptName from Employee
inner join DEPT on Employee.EID =DEPT.EID
)
select * from CTE_Example
让我们逐一掌握声明的每一行并理解。
要定义CTE我们写“with”子句,然后我们给表表达式命名,这里我给出了名称“CTE_Example”
然后我们写“As”并将我们的代码括在两个括号(---)中,我们可以在封闭的括号中连接多个表。
在最后一行中,我使用了“Select * from CTE_Example”,我们在最后一行代码中引用了Common表达式,所以我们可以说它就像一个视图,我们在那里定义和使用视图在单个批处理中,CTE不作为永久对象存储在数据库中。但它的行为就像一个观点。我们可以在CTE上执行删除和更新语句,这将对CTE中使用的引用表产生直接影响。让我们举个例子来理解这个事实。
With CTE_Example(EID,DeptName)
as
(
select EID,DeptName from DEPT
)
delete from CTE_Example where EID=10 and DeptName ='Payroll'
在上面的语句中,我们从CTE_Example中删除一行,它将从CTE中使用的引用表“DEPT”中删除数据。
我希望这篇文章对您有所帮助,只要您觉得合适,您就可以使用CTE。