生成Unique ID以计算各ID对应连续状态的持续时长
解决方案:为连续状态段生成唯一ID并计算总时长
针对同一ID存在多段重复状态的统计问题,核心是通过识别状态变化的分界点为每个连续状态段生成唯一ID,再基于该ID计算分段总时长。以下是具体实现步骤和SQL代码:
核心思路
- 按
id分组、timestamp排序,用LAG()函数获取上一条记录的status - 对比当前记录与上一条的
status,若不同则标记为新分段起点 - 对标记值做累计求和,生成每个连续状态段的
Unique ID - 按
id和Unique ID分组,计算该段的总时长Duration per Status - 将分组统计结果关联回原始数据,得到完整结果表
完整SQL示例
假设你的原始表名为status_logs,已包含id、status、timestamp、end_timestamp、Duration字段:
WITH status_segments AS ( SELECT *, -- 标记状态变化的分界点:当前状态与上一行不同则为1,否则为0 CASE WHEN LAG(status) OVER (PARTITION BY id ORDER BY timestamp) != status THEN 1 ELSE 0 END AS segment_start, -- 累计求和生成Unique ID SUM( CASE WHEN LAG(status) OVER (PARTITION BY id ORDER BY timestamp) != status THEN 1 ELSE 0 END ) OVER (PARTITION BY id ORDER BY timestamp ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + 1 AS unique_id FROM status_logs ), segment_duration AS ( SELECT unique_id, SUM(Duration) AS duration_per_status FROM status_segments GROUP BY unique_id ) SELECT s.id, s.status, s.timestamp, s.end_timestamp, s.Duration, s.unique_id, sd.duration_per_status FROM status_segments s JOIN segment_duration sd ON s.unique_id = sd.unique_id ORDER BY s.id, s.timestamp;
关键函数解释
LAG(status) OVER (PARTITION BY id ORDER BY timestamp):获取同一ID下上一条记录的状态,用于判断是否进入新的连续段SUM(...) OVER (PARTITION BY id ORDER BY timestamp ...):对状态变化标记做累计求和,生成唯一的分段IDSUM(Duration) GROUP BY unique_id:计算每个连续状态段的总时长
最终结果表
| id | status | timestamp | end_timestamp | Duration | Unique ID | Duration per Status |
|---|---|---|---|---|---|---|
| 1 | available | 10/02/2023 10:20:45 | 10/02/2023 10:25:45 | 00:05:00 | 1 | 0:15:00 |
| 1 | available | 10/02/2023 10:25:45 | 10/02/2023 10:30:45 | 00:05:00 | 1 | 0:15:00 |
| 1 | available | 10/02/2023 10:30:45 | 10/02/2023 10:35:45 | 00:05:00 | 1 | 0:15:00 |
| 1 | unavailable | 10/02/2023 10:35:45 | 10/02/2023 10:40:45 | 00:05:00 | 2 | 0:20:00 |
| 1 | unavailable | 10/02/2023 10:40:45 | 10/02/2023 10:45:45 | 00:05:00 | 2 | 0:20:00 |
| 1 | unavailable | 10/02/2023 10:45:45 | 10/02/2023 10:50:45 | 00:05:00 | 2 | 0:20:00 |
| 1 | unavailable | 10/02/2023 10:50:45 | 10/02/2023 10:55:45 | 00:05:00 | 2 | 0:20:00 |
| 1 | waiting | 10/02/2023 10:55:45 | 10/02/2023 11:00:45 | 00:05:00 | 3 | 0:10:00 |
| 1 | waiting | 10/02/2023 11:00:45 | 10/02/2023 11:05:45 | 00:05:00 | 3 | 0:10:00 |
| 1 | available | 10/02/2023 11:05:45 | 10/02/2023 11:10:45 | 00:05:00 | 4 | 0:15:00 |
| 1 | available | 10/02/2023 11:10:45 | 10/02/2023 11:15:45 | 00:05:00 | 4 | 0:15:00 |
| 1 | available | 10/02/2023 11:15:45 | 10/02/2023 11:20:45 | 00:05:00 | 4 | 0:15:00 |
| 2 | unavailable | 10/02/2023 10:20:45 | 10/02/2023 10:25:45 | 00:05:00 | 5 | 0:15:00 |
| 2 | unavailable | 10/02/2023 10:25:45 | 10/02/2023 10:30:45 | 00:05:00 | 5 | 0:15:00 |
| 2 | unavailable | 10/02/2023 10:30:45 | 10/02/2023 10:35:45 | 00:05:00 | 5 | 0:15:00 |
| 2 | waiting | 10/02/2023 10:35:45 | 10/02/2023 10:40:45 | 00:05:00 | 6 | 0:10:00 |
| 2 | waiting | 10/02/2023 10:40:45 | 10/02/2023 10:45:45 | 00:05:00 | 6 | 0:10:00 |
| 2 | unavailable | 10/02/2023 10:45:45 | 10/02/2023 10:50:45 | 00:05:00 | 7 | 0:05:00 |
| 1 | available | 11/02/2023 08:30:45 | 11/02/2023 08:35:45 | 00:05:00 | 8 | 0:10:00 |
| 1 | available | 11/02/2023 08:35:45 | 11/02/2023 08:40:45 | 00:05:00 | 8 | 0:10:00 |
| 1 | waiting | 11/02/2023 08:40:45 | 11/02/2023 08:45:45 | 00:05:00 | 9 | 0:05:00 |
| 1 | available | 11/02/2023 08:45:45 | 11/02/2023 08:50:45 | 00:05:00 | 10 | 0:05:00 |
内容的提问来源于stack exchange,提问作者Paula
相关产品推荐
相关产品推荐

