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

发布于 2024-11-09 06:48:14 字数 1074 浏览 0 评论 0原文

我有一个来自第三方应用程序的名为 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

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

谢谢。

I have this big table called StateChanges (1.9 million rows) from a third party application that contains this data:

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

I need to display the various changes in state for a bunch of components between two dates. This is fairly trivial. However, I display my data this way:

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

The problem I have is that, in order to get the 'initial' status of any given component, I need to get the rows that immediately before the initial date for all the components. There isn't any range we can be sure of, there could have been no changes between 2003 and now.

For a single component, i could get this query to work fast enough:

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

Now, is there a way to get all the "previous states" for all of my components (the ids are in an array) in an effective manner? I've tried:

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

This solutions just happens to be real slow (and give extra results i don't need) compared to the other query that fetches the entire set of changes between the two dates.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浸婚纱 2024-11-16 06:48:14

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

使用此 CTE,您可以按某些条件(即您的 ComponentId)对数据进行分区,并让 SQL Server 对每个分区的所有行进行编号,从 1 开始,按其他一些条件排序 - 即可能 <代码>控制台时间戳。

因此,尝试这样的操作:

;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

在这里,我只为每个“分区”(即每个 ComponentId)选择最后两个条目 - 按 ConsoleTimeStamp 按降序排列。

这接近你正在寻找的东西吗?

I'm not entirely sure I totally understand your question - but one approach would be to use a CTE (Common Table Expression) if you're on SQL Server 2005 and newer (you aren't specific enough in that regard).

With this CTE, you can partition your data by some criteria - i.e. your ComponentId - and have SQL Server number all your rows starting at 1 for each of those partitions, ordered by some other criteria - i.e. probably ConsoleTimeStamp.

So try something like this:

;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

Here, I am selecting only the last two entries for each "partition" (i.e. for each ComponentId) - ordered in a descending fashion by the ConsoleTimeStamp.

Does that approach what you're looking for??

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文