【发布时间】:2013-07-30 17:00:13
【问题描述】:
考虑以下查询...
SELECT
*
,CAST(
(CurrentSampleDateTime - PreviousSampleDateTime) AS FLOAT
) * 24.0 * 60.0 AS DeltaMinutes
FROM
(
SELECT
C.SampleDateTime AS CurrentSampleDateTime
,C.Location
,C.CurrentValue
,(
SELECT TOP 1
Previous.SampleDateTime
FROM Samples AS Previous
WHERE
Previous.Location = C.Location
AND Previous.SampleDateTime < C.SampleDateTime
ORDER BY Previous.SampleDateTime DESC
) AS PreviousSampleDateTime
FROM Samples AS C
) AS TempResults
假设所有事情都相同,例如索引等,这是实现上述结果的最有效方法吗?那是使用子查询来检索最后一条记录吗?
创建一个按 Location、SampleDateTime 排序的游标并为 CurrentSampleDateTime 和 PreviousSampleDateTime 设置变量...在 while 循环的底部将 Previous 设置为 Current 是否会更好?
我不太擅长 CTE,这是否可以通过 CTE 更有效地完成?如果是这样,那会是什么样子?
我可能必须检索 PreviousValue 和 Previous SampleDateTime 才能获得两者的平均值。这会改变结果吗?
长话短说,如果您需要在当前记录的计算中使用这些值,那么保留先前记录值的最佳/最有效方法是什么?
----更新 我应该注意,我在 Location、SampleDateTime、CurrentValue 上有一个聚集索引,所以也许这对结果的影响比什么都大。
有 5,591,571 条记录,我的查询(上一条)平均需要 3 分 20 秒
以下 Joachim Isaksson 的 CTE 平均需要 5 分 15 秒。
也许它需要更长的时间,因为它没有使用聚集索引,而是使用行号进行连接?
我开始测试游标方法,但它已经在 10 分钟...所以不要继续那个。
我会给它一天左右的时间,但我认为我会接受 Joachim Isaksson 提供的 CTE 答案,因为我找到了一种获取最后一行的新方法。
谁能同意是 Location、SampleDateTime、CurrentValue 上的索引使子查询方法更快?
我没有 SQL Server 2012,因此无法测试 LEAD/LAG 方法。我敢打赌,假设微软有效地实现了这一点,那将比我尝试过的任何事情都要快。可能只需要在每一行的末尾交换一个指向内存引用的指针。
【问题讨论】:
-
我至少会使用
MIN而不是TOP 1 x... ORDER BY x(除非该构造是先对 null 进行排序) -
@JoachimIsaksson 但他需要
MAX -
您使用的是哪个版本的 SQL Server?
-
@Lamak 是的,
MAX是有意义的,只需翻译当前查询(可能是错误的)MIN。 -
我问是因为如果使用 2012,您将可以访问
LEAD和LAG。
标签: sql sql-server common-table-expression performance