我有以下查询来选择每个用户的最新订单。使用 CTE 的查询是否有任何性能优势?对于我当前的表,两者都给出了相同的执行计划和时间。
注意:我使用的是 SQL Server 2012
DECLARE @Person TABLE (PersonId INT, NameFirst VARCHAR(100), NameLast VARCHAR(100))
DECLARE @Order TABLE (OrderId INT, PersonId INT, OrderDateTime DATETIME)
--Query1
SELECT A.PersonID,A.NameFirst,A.NameLast, A.OrderID AS LastOrderID,A.OrderDateTime AS LastOrderDateTime
FROM
(
SELECT P.PersonID,P.NameFirst,P.NameLast,O.OrderID,O.OrderDateTime,
ROW_NUMBER() OVER(PARTITION BY O.PersonID ORDER BY O.PersonID,O.OrderDateTime DESC) AS RowNumber
FROM @Person P
LEFT OUTER JOIN @Order O
ON P.PersonId = O.PersonId
)A
WHERE RowNumber = 1
ORDER BY PersonID
--Query2
;WITH CTE AS
(
SELECT P.PersonID,P.NameFirst,NameLast,O.OrderID AS LastOrderID,O.OrderDateTime AS LastOrderDateTime,
ROW_NUMBER() OVER(PARTITION BY O.PersonID ORDER BY O.OrderDateTime DESC) AS RowNumber
FROM @Person P
LEFT OUTER JOIN @Order O
ON P.PersonId = O.PersonId
)
SELECT A.PersonID,A.NameFirst,A.NameLast, A.LastOrderID, A.LastOrderDateTime
FROM CTE A
WHERE RowNumber = 1
ORDER BY PersonID
答案在你的问题中:
当两个计划相同时,生成它们的查询都不可能比另一个有任何性能优势。您的情况相同的时间也仅证实了这一点。
上面的内容至少应该适用于实际(与估计的)计划,但我相信可以完全安全地假设简单地将派生表重写为公用表表达式而不引起任何其他更改不会加速或在 SQL Server 中稍微减慢您的查询速度。
这并不是说 CTE 不能具有其他性质的优势。与派生表相比,CTE 最普遍(尽管可能仍未普遍)公认的优势之一是可读性。我不会在这里详细介绍,因为这超出了问题的范围,但基本上,CTE 可以让您更清晰地将查询拆分为逻辑步骤,并使您能够更自然地遵循不熟悉的脚本的逻辑。