SQL Server:获取在特定日期之前发生的给定组件集的最后记录

时间:2011-05-20 17:49:21

标签: sql-server date

我有来自包含此数据的第三方应用程序的名为StateChanges(190万行)的大表:

[ComponentID] : integer : Id of what changed
[NewStatus] : integer : How it changed (0: OK, 1: Error, 2:Warning)
[ConsoleTimeStamp] : timestamp, index : When it changed.

我需要在两个日期之间显示一堆组件的各种状态变化。这是相当微不足道的。但是,我以这种方式显示我的数据:

[OldStatus] --> [New Status] | [ConsoleTimeStamp]

我遇到的问题是,为了获得任何给定组件的“初始”状态,我需要获取所有组件的初始日期之前的行。我们无法确定任何范围,2003年至今之间可能没有任何变化。

对于单个组件,我可以让这个查询足够快地运行:

SELECT TOP 1 [NewStatus], [ConsoleTimeStamp] FROM [StateChanges] 
WHERE [ComponentID] = ? AND [ConsoleTimeStamp] < ?
ORDER BY [ConsoleTimeStamp] DESC

现在,是否有办法以有效的方式获取所有组件的所有“以前的状态”(ID在数组中)?我试过了:

SELECT ComponentId, NewStatus, MAX(ConsoleTimeStamp) As LastDate FROM StateChanges
WHERE ComponentId IN ({0}) AND ConsoleTimeStamp <= ?
GROUP BY ComponentId,NewStatus
ORDER BY ComponentId ASC, LastDate ASC

与在两个日期之间获取整个更改集的其他查询相比,此解决方案恰好是真正的慢(并且提供了我不需要的额外结果)。

谢谢。

1 个答案:

答案 0 :(得分:1)

我不完全确定我完全理解你的问题 - 但如果你使用的是SQL Server 2005及更新版本(在这方面你不够具体),一种方法是使用CTE(公用表表达式)

使用此CTE,您可以按照某些条件对数据进行分区 - 即您的ComponentId - 并且SQL Server编号的所有行从1开始为每个分区排序,按其他一些标准排序 - 即可能{ {1}}。

所以尝试这样的事情:

ConsoleTimeStamp

在这里,我只选择每个“分区”的最后两个条目(即每个;WITH PartitionedComponents AS ( SELECT ComponentId, NewStatus, ConsoleTimeStamp, ROW_NUMBER() OVER(PARTITION BY ComponentId ORDER BY ConsoleTimeStamp DESC) AS 'RowNum' FROM dbo.StateChanges WHERE ComponentId IN (.....) AND ConsoleTimeStamp <= (threshold) ) SELECT ComponentId, NewStatus, ConsoleTimeStamp, RowNum FROM PartitionedComponents WHERE RowNum <= 2 ) - 由ConsoleTimeStamp以降序排序。

这会接近你想要的吗?