我有来自包含此数据的第三方应用程序的名为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
与在两个日期之间获取整个更改集的其他查询相比,此解决方案恰好是真正的慢(并且提供了我不需要的额外结果)。
谢谢。
答案 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以降序排序。
这会接近你想要的吗?