同一列和按天分组的值的日期时间总和

时间:2019-07-18 02:28:07

标签: mysql

我有一个表,其中列活动的值分别为“ ON”和“ OFF”,而另一列日期时间为

id(AUTOINCREMENT) id_device     activity    datetime
 1                    a            ON        2017-05-26 22:00:00
 2                    b            ON        2017-05-26 05:00:00
 3                    a            OFF       2017-05-27 04:00:00
 4                    b            OFF       2017-05-26 08:00:00
 5                    a            ON        2017-05-28 12:00:00
 6                    a            OFF       2017-05-28 15:00:00

我需要每天获取总计开机时间

day           id_device     total_minutes_on
2017-05-26      a               120
2017-05-26      b               180
2017-05-27      a               240
2017-05-27      b               0
2017-05-28      a               180
2017-05-28      b               0

我已经搜索并尝试了其他帖子的答案,我尝试了TimeDifference,并获得了正确的总时间。 我找不到按日期分组总时间的方法

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

我并不是将其发布为一个明确的答案,而是对我来说是一个实验,希望您会发现对您的情况有用。我还要提及的是,我正在使用的MySQL数据库版本已经很旧了,因此至少可以说,我使用的方法也是非常手动的。

首先让我们提取您的预期输出:

  1. day中的日期值需要在id_device ab中重复两次。
  2. 分钟数是根据活动计算的;如果活动在明天之前一直为“开”,则需要计算该活动,直到一天的结束时间为24:00:00,而第二天将计算分钟,直到活动为OFF

我想出的是这样的:

  • 创建条件(1):
SELECT * FROM
(SELECT DATE(datetime) dtt FROM mytable GROUP BY DATE(datetime)) a,
(SELECT id_device FROM mytable GROUP BY id_device) b
ORDER BY dtt,id_device;

上面的查询将返回以下结果:

+------------+-----------+
|    dtt     | id_device |
+------------+-----------+
| 2017-05-26 | a         |
| 2017-05-26 | b         |
| 2017-05-27 | a         |
| 2017-05-27 | b         |
| 2017-05-28 | a         |
| 2017-05-28 | b         |
+------------+-----------+

*以上仅适用于表格中的所有日期。如果您想获得所有日期,而不管是否有活动,建议您创建一个日历表(请参阅:Generating a series of dates)。

因此这成为基本查询。然后,我添加了一个外部查询,以使上面的查询与原始数据表左连接:

SELECT v.*,
      GROUP_CONCAT(w.activity ORDER BY w.datetime SEPARATOR ' ') activity, 
      GROUP_CONCAT(TIME_TO_SEC(TIME(w.datetime)) ORDER BY w.datetime SEPARATOR ' ') tr 
FROM
-- this was the first query
(SELECT * FROM
(SELECT DATE(datetime) dtt FROM mytable GROUP BY DATE(datetime)) a,
(SELECT id_device FROM mytable GROUP BY id_device) b
ORDER BY a.dtt,b.id_device) v 
-- 
LEFT JOIN
mytable w
ON v.dtt=DATE(w.datetime) AND v.id_device=w.id_device
GROUP BY DATE(v.dtt),v.id_device

查询中的新增功能是对从datetime列提取的活动和时间值添加了GROUP_CONCAT操作,该操作和时间值转换为秒值。您会注意到,在两个GROUP_CONCAT中都有一个相似的ORDER BY条件,这对于获取确切的对应值很重要。 上面的查询将返回以下结果:

+------------+-----------+----------+-------------+
|    dtt     | id_device | activity |     tr      |
+------------+-----------+----------+-------------+
| 2017-05-26 | a         | ON       | 79200       |
| 2017-05-26 | b         | ON OFF   | 18000 28800 |
| 2017-05-27 | a         | OFF      | 14400       |
| 2017-05-27 | b         | (NULL)   | (NULL)      |
| 2017-05-28 | a         | ON OFF   | 43200 54000 |
| 2017-05-28 | b         | (NULL)   | (NULL)      |
+------------+-----------+----------+-------------+

从这里,我在外面添加了另一个查询,以计算多少分钟并尝试获得预期的结果:

SELECT dtt,id_device,
      CASE
      WHEN SUBSTRING_INDEX(activity,' ',1)='ON' AND SUBSTRING_INDEX(activity,' ',-1)='OFF' 
      THEN (SUBSTRING_INDEX(tr,' ',-1)-SUBSTRING_INDEX(tr,' ',1))/60 

      WHEN activity='ON' THEN 1440-(tr/60)

      WHEN activity='OFF' THEN tr/60

      WHEN activity IS NULL AND tr IS NULL THEN 0

      END AS 'total_minutes_on' 
FROM
-- from the last query
(SELECT v.*,
      GROUP_CONCAT(w.activity ORDER BY w.datetime SEPARATOR ' ') activity, 
      GROUP_CONCAT(TIME_TO_SEC(TIME(w.datetime)) ORDER BY w.datetime SEPARATOR ' ') tr 
FROM
-- this was the first query
(SELECT * FROM
(SELECT DATE(datetime) dtt FROM mytable GROUP BY DATE(datetime)) a,
(SELECT id_device FROM mytable GROUP BY id_device) b
ORDER BY a.dtt,b.id_device) v 
-- 
LEFT JOIN
mytable w
ON v.dtt=DATE(w.datetime) AND v.id_device=w.id_device
GROUP BY DATE(v.dtt),v.id_device
--
) z

我要做的最后一部分是,如果activity值在同一天同时具有ONOFF,那么(OFF-ON)/ 60secs =总分钟数。如果activity的值仅为ON,则'24:00:00'的分钟值> 24小时* 60分钟= 1440-(ON / 60secs)=总分钟数,并且如果活动仅OFF,我只是将秒转换为分钟,因为无论如何一天都是从00:00:00开始。

+------------+-----------+------------------+
|    dtt     | id_device | total_minutes_on |
+------------+-----------+------------------+
| 2017-05-26 | a         |              120 |
| 2017-05-26 | b         |              180 |
| 2017-05-27 | a         |              240 |
| 2017-05-27 | b         |                0 |
| 2017-05-28 | a         |              180 |
| 2017-05-28 | b         |                0 |
+------------+-----------+------------------+

希望这会给您一些想法。 ;)