【发布时间】:2022-01-18 04:12:40
【问题描述】:
我尝试用 Google 搜索在查询中使用 Top 与使用 Ranking 或 Row_Number 类型函数的成本。
每个功能的成本是否取决于具体情况,或者这两个功能的成本是否可以针对所有情况全面确定?
下面的一些模拟 SQL 使用简单的 CTE 来演示我的问题,如下所示:
WITH fData AS
(
SELECT 1 AS ID, 'John' AS fName, 'Black' AS lName, CAST('05/19/1975' AS DATE) AS birthDate UNION ALL
SELECT 2 AS ID, 'John' AS fName, 'Black' AS lName, CAST('04/1/1989' AS DATE) AS birthDate UNION ALL
SELECT 3 AS ID, 'John' AS fName, 'Black' AS lName, CAST('11/16/1995' AS DATE) AS birthDate UNION ALL
SELECT 4 AS ID, 'John' AS fName, 'Black' AS lName, CAST('01/16/1968' AS DATE) AS birthDate UNION ALL
SELECT 5 AS ID, 'John' AS fName, 'Black' AS lName, CAST('01/16/1968' AS DATE) AS birthDate
)
/* Using TOP 1 vs Row_Number() - Uncomment this and comment the below to VIEW TOP version */
--SELECT TOP 1 d.ID, d.fName, d.lName, d.birthDate
--FROM fData d
--ORDER BY d.birthDate
/* Using the below vs TOP 1 */
SELECT * FROM
( SELECT d.ID, d.fName, d.lName, d.birthDate, Row_Number() OVER (ORDER BY d.birthDate) AS ranker
FROM fData d
) r
WHERE r.ranker = 1
使用 TOP 时,无需在其周围应用辅助 Wrapping 查询,它看起来更干净。在应用 Row_Number 或 Ranking 函数后,您必须将其包装以告诉查询您现在想要哪一行...通过应用 WHERE ranker = 1 或 ranker >= 5 来达到与 TOP 1 或 TOP 5 相同的效果。
如果这是可以确定的,哪个更快?
【问题讨论】:
-
查看查询计划。您会注意到
TOP (1)的查询计划与使用ROW_NUMBER和WHERE {ROW_NUMBER()} = 1相比是完全不同的。 Simple example -
它们解决了一个不同的问题 - top 用于当您希望在整个结果集中有一行时。行号用于当您想要每个分区的第一行时。
-
它当然可以确定(通过执行计划),但要非常小心地得出一般性结论,因为关于构造 X 总是比构造 Y 更快的笼统陈述很少见。查询上下文很重要。 (另外,do not use locale-dependent date formats。)
-
^^ 嗯,是的,非常正确,但是从没有 TOP 的 Oracle 到现在在 SQL Server 商店……TOP 到处都在使用,很好……但我也可以看到到处都是 Row_Number() 函数,然后或 course 然后用 WHERE ranker = 1 的过滤器包装......所有时间。为什么在 SQL Server 中有 TOP 时使用排名函数?这两个功能解决了相同的问题,而不是我看到它们解决不同的问题。
-
不能用
TOP替换带有PARTITION BY的ROW_NUMBER()子句(或者至少不是没有相当大的困难)。如果您有多个此类订单,则同上;具有多个ROW_NUMBER()s 的单个查询,您稍后过滤它可能优于使用TOP的一组单独的查询。您编写的简单表格确实(实际上)总是在 T-SQL 中使用TOP而不是ROW_NUMBER(),但将ROW_NUMBER()添加到语言中是有原因的。