我的 SQL Server 中有以下场景,确切的命名或内容并不重要,更重要的是我需要执行的操作。
每个 id 可以有多行
id | 时间戳 | 数据值 | 状态 |
---|---|---|---|
1 | 2023-09-01 08:00:00 | 10.5 | |
1 | 2023-09-01 08:30:00 | 11.2 | |
1 | 2023-09-01 09:00:00 | 9.8 | |
2 | 2023-09-01 08:15:00 | 7.3 | |
2 | 2023-09-01 08:45:00 | 8.0 |
每个 id 可以有多行,句点不重叠。
id | 开始时间戳 | 停止时间戳 | 状态 |
---|---|---|---|
1 | 2023-09-01 08:00:00 | 2023-09-01 08:45:00 | 完成 |
1 | 2023-09-01 08:15:00 | 2023-09-01 09:00:00 | 未完成 |
1 | 2023-09-01 09:00:00 | 2023-09-01 09:15:00 | 完成 |
2 | 2023-09-01 08:15:00 | 2023-09-01 09:00:00 | 完成 |
2 | 2023-09-01 09:00:00 | 2023-09-01 09:55:00 | 未完成 |
两张表的大小每天都在增长。 我想要实现的是,如果 [Items].timestamp 适合相应的 [ItemsMaintenance].start_timestamp 和 [项目维护].stop_timestamp. 因此,在这种情况下,[Items] 的第一行应更新为
done,因为它位于 [ItemsMaintenance] 中第一行的值之间。 假设冲突的重叠
ItemsMaintenance
。
UPDATE I
SET status = IM.status
FROM Items I
JOIN ItemsMaintenance IM
ON IM.id = I.id
AND IM.start_timestamp <= I.timestamp
AND IM.stop_timestamp > I.timestamp
WHERE I.status IS DISTINCT FROM IM.status -- Don't update values already set
如果您的数据实际上可能包含重叠冲突的 ItemsMaintenance
行,您将需要定义一个应用规则,并使用
CROSS APPLY (SELECT TOP 1 ...)
选择应应用的规则。以下人员将更喜欢具有最新
ItemsMaintenance
的 start_timestamp
行。UPDATE I
SET status = IM.status
FROM Items I
CROSS APPLY (
SELECT TOP 1 *
FROM ItemsMaintenance IM
WHERE IM.id = I.id
AND IM.start_timestamp <= I.timestamp
AND IM.stop_timestamp > I.timestamp
ORDER BY IM.start_timestamp DESC
) IM
WHERE I.status IS DISTINCT FROM IM.status -- Don't update values already set
IS DISTINCT FROM
比较类似于
<>
(不等于),但也可以安全地处理
NULL
值。尝试这样的事情: