sql server中公用表表达式的优点是什么

Tho*_*mas 12 sql t-sql sql-server common-table-expression

我们写下一个CTE sql

WITH yourCTE AS 
(
 SELECT .... FROM :... WHERE.....
) SELECT * FROM yourCTE
Run Code Online (Sandbox Code Playgroud)

将sql放入块中会有什么好处.我认为,如果我们把复杂的sql放入块中,那么我们就可以编写像sql一样的了SELECT * FROM yourCTE.好像我正在访问视图.在性能方面使用CTE的附加优势是什么.请讨论.谢谢

mar*_*c_s 15

在许多情况下,CTE可能非常有用:

  • 递归查询,比如走一个层次结构树 - 没有CTE就非常棘手和繁琐(请参阅此处获取递归CTE的示例)

  • 任何时候你要使用的一个排序函数一样ROW_NUMBER(),RANK(),NTILE()等等(见此处查看详情上排名函数)

  • 通常情况下,您需要首先根据某些条件选择几行/列,然后对这些行执行某些操作,例如更新表,删除重复项等.

我经常使用CTE的一个案例是删除除给定数据集的最新行之外的所有行,例如,如果您有客户并且与他们的订单有1:n关系,并且您想要删除除最近订单之外的所有订单(基于a OrderDate),对于每个客户,在没有CTE的情况下在SQL中执行此操作会非常繁琐.

有了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
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以创建一个"内联视图",该分区依据CustomerID(例如,每个客户从1开始获得rownumbers),顺序排序OrderDate DESC(最新订单优先).对于每个客户,最新的,最近的订单都有RowN = 1,所以你可以轻松地删除所有其他行,你已经完成了你想做的事情 - 一块蛋糕与CTE - 没有它的凌乱代码....


Far*_*den 3

这篇 MSDN 文章对此进行了最好的描述。最重要的是,如果您已经从视图中选择数据,则不必将其包装在 CTE 中,然后从 CTE 中选择。我认为 CTE 和视图之间没有太大区别(性能方面)。至少以我的经验来看不是(而且我最近一直在使用一些包含大量记录的复杂数据库结构)。然而,CTE 对于递归选择来说是理想的选择。

不过,另一件事是,如果您在查询中多次选择连接数据的相同子集并且没有为其定义视图,那么 CTE 可能会很有用。我认为如果您只是为了单个查询而连接数据,然后将其包装在 CTE 中,那就太过分了。即使您没有使用 CTE,查询路径仍然会被缓存...