SQL Server 将日期时间行合并到一行中,并在其他列的值发生变化时进行拆分

Moh*_*jem 4 sql-server

我正在尝试在 SQL 中创建一个视图,该视图合并开始日期时间和最后日期时间,并在值列更改时进行拆分,因为知道日期差异的值不固定。例如我有一个表名称 Sensors:

传感器ID 开始时间 时间结束 价值
14033 2023-05-01 00:00:00.000 2023-05-01 00:05:00.000 0
14033 2023-05-01 00:05:00.000 2023-05-01 00:20:00.000 1
14033 2023-05-01 00:20:00.000 2023-05-01 03:00:00.000 1
14033 2023-05-01 03:00:00.000 2023-05-01 12:00:00.000 1
14033 2023-05-01 12:00:00.000 2023-05-01 20:00:00.000 0
14033 2023-05-01 20:00:00.000 2023-05-01 22:59:59.000 0

结果必须如下表所示:

传感器ID 开始时间 时间结束 价值
14033 2023-05-01 00:00:00.000 2023-05-01 00:05:00.000 0
14033 2023-05-01 00:05:00.000 2023-05-01 12:00:00.000 1
14033 2023-05-01 12:00:00.000 2023-05-01 22:59:59.000 0

Sab*_*n B 6

基于此示例,这里是一些代码,受到 Itzik Ben-Gan 的启发,特殊岛屿解决方案链接。
(我添加了 CTE 以便更好地理解)

CREATE VIEW dbo.vw_Sensors
AS

    with CTE_Source AS
    (
        SELECT *    ,
            LAG(EndTime,1,NULL) OVER(PARTITION BY SensorID ORDER BY StartTime) as EndTime_prev,
            LAG(Value,1,NULL) OVER(PARTITION BY SensorID ORDER BY StartTime) as Value_prev
        FROM dbo.Sensors
    )
    ,CTE_Source2 AS
    (
        SELECT * ,
            CASE WHEN s.StartTime <> ISNULL(s.EndTime_prev,'19000101') THEN 1
                 WHEN s.Value <> ISNULL(s.Value_prev,-1) THEN 1
                 ELSE 0 
            END as IsGrp
        FROM CTE_Source as s
    )
    ,CTE_Source3 AS
    (
        SELECT * ,
            SUM(s.isGrp) OVER(PARTITION BY s.SensorID  ORDER BY StartTime ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as sumGrp
        FROM CTE_Source2 as s
    )
    SELECT s.SensorID,
        MIN(s.StartTime) as StartTime,
        MAX(s.EndTime) as EndTime,
        MAX(s.Value) as Value
    FROM CTE_Source3 as s
    GROUP BY 
        s.SensorID,
        s.sumGrp
GO
Run Code Online (Sandbox Code Playgroud)

输出:

传感器ID 开始时间 时间结束 价值
14033 2023-05-01 00:00:00.000 2023-05-01 00:05:00.000 0
14033 2023-05-01 00:05:00.000 2023-05-01 12:00:00.000 1
14033 2023-05-01 12:00:00.000 2023-05-01 22:59:59.000 0

数据库小提琴

在步骤 1(第一个)中,我们只计算和 的select先前值EndTimeValue

传感器ID 开始时间 时间结束 价值 结束时间_上一个 上一个值
14033 2023-05-01 00:00:00.000 2023-05-01 00:05:00.000 0 无效的 无效的
14033 2023-05-01 00:05:00.000 2023-05-01 00:20:00.000 1 2023-05-01 00:05:00.000 0
14033 2023-05-01 00:20:00.000 2023-05-01 03:00:00.000 1 2023-05-01 00:20:00.000 1

StartTime步骤2,如果和之间有差异,或者和 之间previous EndTime有差异,那么我们将此行标记为Valueprevious Value1 = IsGrp

传感器ID 开始时间 时间结束 价值 结束时间_上一个 上一个值 是Grp
14033 2023-05-01 00:00:00.000 2023-05-01 00:05:00.000 0 无效的 无效的 1
14033 2023-05-01 00:05:00.000 2023-05-01 00:20:00.000 1 2023-05-01 00:05:00.000 0 1
14033 2023-05-01 00:20:00.000 2023-05-01 03:00:00.000 1 2023-05-01 00:20:00.000 1 0

在步骤 3 中,我们应用SUM这个新字段 (isGrp) 。

传感器ID 开始时间 时间结束 价值 结束时间_上一个 上一个值 是Grp 总和
14033 2023-05-01 00:00:00.000 2023-05-01 00:05:00.000 0 无效的 无效的 1 1
14033 2023-05-01 00:05:00.000 2023-05-01 00:20:00.000 1 2023-05-01 00:05:00.000 0 1 2
14033 2023-05-01 00:20:00.000 2023-05-01 03:00:00.000 1 2023-05-01 00:20:00.000 1 0 2
14033 2023-05-01 03:00:00.000 2023-05-01 12:00:00.000 1 2023-05-01 03:00:00.000 1 0 2

最后一步/选择只是聚合这些信息以显示所需的输出