SQL 查找一组中两个值之间的时间差

SQL to find time difference between two values in a group

我有一个 sql table 如下所示。

+---------------------+--------+-------+
|        time         | item   | state |
+---------------------+--------+-------+
| 2019-07-19 1:50:00 | a      |   st1 |
| 2019-07-19 2:51:00 | a      |   st2 |
| 2019-07-19 2:55:00 | b      |   st1 |
| 2019-07-19 2:59:00 | b      |   st2 |
| 2019-07-19 4:30:00 | a      |   st3 |
+---------------------+--------+-------+

我需要弄清楚项目从 st1 到 st2 等状态更改花费了多少时间..

最终输出 table 应如下所示。

+--------+------------+---------------+
| item   | st1_to_st2 |   st2_to_st3  | and so on
+--------+------------+---------------+
| a      |   x seconds| w-seconds     |
| b      |   y-seconds| z-seconds     |
+--------+------------+---------------+

你能帮我 sql 吗?

对于固定的状态列表,您可以使用window函数和聚合:

select item,
    sum(case when lag_state = 'st1' and state = 'st2' then timestampdiff(second, lag_time, time)) as st1_to_st2,
    sum(case when lag_state = 'st2' and state = 'st3' then timestampdiff(second, lag_time, time)) as st2_to_st3
from (
    select t.*,
        lag(time)  over(partition by item order by state) lag_time,
        lag(state) over(partition by item order by state) lag_state
    from mytable t
) t
group by item

如果您想要更通用的东西 - 即不对状态进行硬编码 - 我建议将值放在行中而不是列中:

select item, lag_state, state, 
    sum(timestampdiff(second, lag_time, time)) as sum_diff
from (
    select t.*,
        lag(time)  over(partition by item order by state) lag_time,
        lag(state) over(partition by item order by state) lag_state
    from mytable t
) t
group by item, lag_state, state