表DEVICE_STATUS

Id Status Timestamp
1 Active 2023-01-13T18.00.01.0187528
2 Active 2023-01-13T18.00.01.0187529
1 Failed 2023-01-13T18.00.01.0187530
3 Active 2023-01-13T18.00.01.0187531
1 Failed 2023-01-13T18.00.01.0187532
1 Active 2023-01-13T18.00.01.0187533
3 Active 2023-01-13T18.00.01.0187534
1 Failed 2023-01-13T18.00.01.0187535
4 Failed 2023-01-13T18.00.01.0187536
1 Active 2023-01-13T18.00.01.0187537

预期输出(需要生成SQL查询):

ID Fail_Begin Fail_End
1 2023-01-13T18.00.01.0187530 2023-01-13T18.00.01.0187532
1 2023-01-13T18.00.01.0187535 2023-01-13T18.00.01.0187535
4 2023-01-13T18.00.01.0187536 2023-01-13T18.00.01.0187536

基本上,对于每个ID,获取min(时间戳)和max(时间戳),但对于该ID的连续记录.如果只有一条记录,则min=max,就像示例结果集中的第二条和第三条记录一样.

我try 过这个(以及它的各种子查询变体)

SELECT Id, min(Timestamp) AS Fail_Begin, max(Timestamp) AS Fail_End
FROM Device_Status
GROUP BY Id

但只需要按连续出现的记录分组,

因此,或许先加入地位变化的概念会有所帮助?从零开始作为初始状态,然后在每次下一条记录不同时将改变码加1,从而生成如下所示的中间结果...

表DEVICE_STATUS_With_Change_Column

Id Status Change Timestamp
1 Active 0 2023-01-13T18.00.01.0187528
2 Active 0 2023-01-13T18.00.01.0187529
1 Failed 1 2023-01-13T18.00.01.0187530
3 Active 0 2023-01-13T18.00.01.0187531
1 Failed 1 2023-01-13T18.00.01.0187532
1 Active 2 2023-01-13T18.00.01.0187533
3 Active 0 2023-01-13T18.00.01.0187534
1 Failed 3 2023-01-13T18.00.01.0187535
4 Failed 0 2023-01-13T18.00.01.0187536
1 Active 4 2023-01-13T18.00.01.0187537

然后再做

SELECT Id, Change, min(Timestamp) AS Fail_Begin, max(Timestamp) AS Fail_End
FROM Device_Status_With_Change_Column
GROUP BY Id, Change

除了在编程语言中循环结果集之外,我还没有看到一个直接的SQL语句可以在没有中间表的情况下一举做到这一点,我也不知道如何计算列更改(在SQL中).

推荐答案

下面的解决方案首先使用子查询将行号与每个failed条记录相关联,该行号由id块划分.然后,该子查询被join赋给其自身:

with cte as (
   select row_number() over (partition by t.id order by t.timestamp) r, t.* 
   from device_status t where t.status = 'Failed'
)
select c.id, c.timestamp fail_start, coalesce(c1.timestamp, c.timestamp) fail_end
from cte c left join cte c1 on c.id = c1.id and c.r + 1 = c1.r
where c.r % 2 = 1

See fiddle

Sql相关问答推荐

删除事务中的本地临时表

NULL-生成的列中连接的字符串的输入

根据Rails活动记录中时间戳/日期时间的时间部分从PostgreSQL中提取记录

将结果从一列转换为两行或更多

在xml.Modify方法中使用子字符串和可能的替代方法

将两列相加为同一表中的行的查询

根据时间、状态和相关行在PostgreSQL中的存在来删除行

如何为缺少的类别添加行

使用递归CTE在BigQuery中获取文件路径

不存在记录的国外关键点

统计重复记录的总数

将时间戳四舍五入到最近 10 分钟的查询

查询中获取审批者不起作用

如何在插入时将字符串'03-January-2023'转换为日期时间

SQL查询以获取从特定可变日期看到的用户

PostgresQL-根据另一列找到 3 个最低值

如何使用 pg-promise 创建要在复杂的 sql 查询中使用的 VALUES 列表?

在 sql 中合并系列以删除重复项

SQL中所有先前日期的累计总和

Oracle SQL 查询自行运行,但在包装到select count(*) from ()时失败