计算每种状态的时间

时间:2019-12-03 19:21:29

标签: mysql select

我的下表如下。

timeStamp是状态开始的时刻。 如果状态发生更改,有些行不会添加新信息(例如第二行),因此可以忽略它们。

我将使用mysql 5.7计算每种状态的总时间。

|      timeStamp      | status |
|------------------------------|
| 2019-12-10 14:00:00 |   1    |  
| 2019-12-10 14:10:00 |   1    | // this row could be ignored
| 2019-12-10 14:00:00 |   2    | // more 24 hours in status 1
| 2019-12-11 14:10:00 |   2    | 
| 2019-12-12 14:00:00 |   1    | // more 24 hours in status 2
| 2019-12-14 14:00:00 |   2    | // more 48 hours in status 1
| 2019-12-16 14:10:00 |   2    |
| 2019-12-17 14:20:00 |   2    | 
| 2019-12-18 14:00:00 |   3    | // more 96 hours in status 2
| 2019-12-19 14:00:00 |   1    | // more 24 hours in status 3

我希望看到一个像波纹管这样的表。

| status | amount_of_time |
|-------------------------|
|    1   |     72 hours   |
|    2   |     120 hours  |
|    3   |     24 hours   |

令此问题复杂化的是,状态不按顺序排列:不是1,2,3。 在上面的示例中,它是:1、2、1、2、3、1,所以我不能使用MIN信息。

1 个答案:

答案 0 :(得分:3)

在子查询中获取下一行的时间戳,并计算与当前行的时间戳之差:

select t1.status, timestampdiff(second,
  t1.timeStamp,
  (
    select min(t2.timeStamp)
    from mytable t2
    where t2.timeStamp > t1.timeStamp
  )
) as diff                     
from mytable t1;

这将返回:

| status | diff   |
| ------ | ------ |
| 1      | 600    |
| 1      | 86400  |
| 2      | 600    |
| 2      | 85800  |
| 1      | 172800 |
| 2      | 173400 |
| 2      | 87000  |
| 2      | 85200  |
| 3      | 86400  |
| 1      | NULL   |

View on DB Fiddle

从这里开始,只需要GROUP BYSUM

select status, sum(diff) as duratation_in_seconds
from (
  select t1.status, timestampdiff(second,
    t1.timeStamp,
    (
      select min(t2.timeStamp)
      from mytable t2
      where t2.timeStamp > t1.timeStamp
    )
  ) as diff                     
  from mytable t1
) x
group by status;

结果:

| status | duratation_in_seconds |
| ------ | --------------------- |
| 1      | 259800                |
| 2      | 432000                |
| 3      | 86400                 |

View on DB Fiddle

如果您希望以小时为单位,请将第一行更改为

select status, round(sum(diff)/3600) as duratation_in_hours

您将获得:

| status | duratation_in_hours |
| ------ | ------------------- |
| 1      | 72                  |
| 2      | 120                 |
| 3      | 24                  |

View on DB Fiddle

您可能希望使用floor()而不是round()。你的问题不清楚。

在MySQL 8中,您可以使用LEAD()窗口函数来获取下一行的时间戳:

select status, sum(diff) as duratation_in_seconds
from (
  select 
    status,
    timestampdiff(second, timeStamp, lead(timeStamp) over (order by timeStamp)) as diff
  from mytable
) x
group by status;

View on DB Fiddle