我有一个表,其中包含许多资源的状态历史记录(包括当前状态)。它看起来像这样:
CREATE TABLE [dbo].[RESOURCE_STATUS](
[id] [int] IDENTITY(1,1) NOT NULL,
[resource_id] [int] NOT NULL,
[date_timestamp] [datetime] NOT NULL,
[end_timestamp] [datetime] NULL,
...
)
数据的一个例子(显然代表一个有效的时间戳):
+------+-------------+-----------------+---------------+
| id | resource_id | start_timestamp | end_timestamp |
+------+-------------+-----------------+---------------+
| 1 | 1 | <valid_ts> | <valid_ts> |
| 2 | 2 | <valid_ts> | <valid_ts> |
| 3 | 3 | <valid_ts> | NULL |
| 4 | 1 | <valid_ts> | NULL |
| 5 | 2 | <valid_ts> | NULL |
| 6 | 1 | <valid_ts> | <valid_ts> |
| 7 | 2 | <valid_ts> | NULL |
| 8 | 1 | <valid_ts> | NULL |
+------+-------------+-----------------+---------------+
当然,还有其他列代表状态等,但我认为此时并不相关。
理论上,每个记录中的start_timestamp和end_timestamp应该用NULL end_timestamp指示每个状态的开始和结束的日期和时间,指示状态正在进行(在这种情况下,行3,7和8表示正在进行的状态。)
我遇到的问题是,在某些情况下(示例中的第4行和第5行),end_timestamp尚未设置并且为了使我们的报告系统正常工作,我需要返回并从start_timestamp中设置该时间戳。该集合中该资源的下一条记录(如果存在)。 I.E.从第6行更新第4行,从第7行更新第5行。不应修改第3,7和8行,因为它们代表资源的当前状态。
请注意,缺少end_timestamp的行可能不是该resource_id的第一行,并且可能有多个行用于一个或多个具有错误的NULL end_timestamps的资源。
我需要为现有数据执行此操作,并在将数据添加到表中时持续进行此操作(我知道数据的创建者应该是固定的,但出于各种原因而不是在此表中点)。
如果它是相关的,我们正在使用MS SQL Server 2008,该表目前只包含超过200万行,并且显然每天都在增长。
有人可以帮我解决这个问题吗?
答案 0 :(得分:1)
试试这个......
WITH AddRowNumber AS
(
SELECT
id
, resource_id
, start_timestamp
, end_timestamp
, ROW_NUMBER() OVER(PARTITION BY resource_id ORDER BY start_timestamp) AS RowNumber
FROM
@Resource_Status
)
, NewTimestamp AS
(
SELECT
A1.id
, A1.resource_id
, A1.start_timestamp
, A1.end_timestamp
, A2.start_timestamp AS NewEndTimeStamp
FROM
AddRowNumber AS A1
INNER JOIN
AddRowNumber AS A2
ON
A1.resource_id = A2.resource_id
AND A1.RowNumber = A2.RowNumber - 1
WHERE
A1.end_timestamp IS NULL
)
UPDATE
@Resource_Status
SET
end_timestamp = Nt.NewEndTimeStamp
FROM
@Resource_Status AS R
INNER JOIN
NewTimestamp AS NT
ON
R.id = NT.id
如果有效,请告诉我。
灰