每天多个持续时间的SUM时间戳记

时间:2019-01-21 22:34:14

标签: mysql

我要从恒温器中取出一张桌子。 它记录数据如下。 因此,当它打开时,我得到一个状态为1的时间状态,状态0表示加热关闭。此外,它还为我提供了每天打开/关闭总加热的功能。

Date                | Status | Total_heatings
2019-01-20 10:00:00 | 1      | 1
2019-01-20 10:10:00 | 0      | 1
2019-01-20 14:00:00 | 1      | 2
2019-01-20 14:25:00 | 0      | 2
2019-01-20 18:00:00 | 1      | 3
2019-01-20 18:15:00 | 0      | 3
2019-01-21 01:00:00 | 1      | 1
2019-01-21 01:30:00 | 0      | 1
2019-01-21 06:00:00 | 1      | 2
2019-01-21 06:15:00 | 0      | 2

我正在尝试获取每天的总时长。我尝试了以下脚本,该脚本为我提供了每天多次加热的持续时间。 当我使用SUM(TIMESTAMPDIFF(Minute,Min(Date),MAX(Date)))时,由于使用分组错误而引发错误。

SELECT 
   DATE_FORMAT(Date, '%d.%m') AS 'day',
   TIMESTAMPDIFF(MINUTE,MIN(Date),MAX(Date)) AS 'Duration'
FROM thermostat 
   WHERE (Date BETWEEN '2019-01-21 00:00:00' + INTERVAL -7 DAY AND '2019-01-21 00:00:00') 
   GROUP BY DAY(Date),Total_heatings;

我需要做的就是每天获取这些各种供暖时段的总和。 因此结果应具有以下内容:

Day   | Duration
20.01 | 50
21.01 | 45

现在,我无法继续汇总每天的所有加热时间,例如每天的总持续时间。 非常感谢您的指导和帮助。

3 个答案:

答案 0 :(得分:0)

如果使用的是MySQL 8,则可以使用窗口函数LAG访问上一个开关。在外部查询中,您可以过滤以前状态为打开的时间间隔。

SELECT
    DATE_FORMAT(x.date, '%d.%m'),
    SUM(TIMESTAMPDIFF( minute, x.date, x.last_date) duration
FROM (
    SELECT 
        t.*,
        LAG(t.date) OVER (PARTITION BY DATE_FORMAT(t.date, '%d.%m') ORDER BY t.date) last_date,
        LAG(t.status) OVER (PARTITION BY DATE_FORMAT(t.date, '%d.%m') ORDER BY t.date) last_status
    FROM mytable t
) x
WHERE x.last_status = 1
GROUP BY DATE_FORMAT(x.date, '%d.%m')
ORDER BY 1

this db fiddle中,这与您的预期输出匹配。

答案 1 :(得分:0)

Using window function在MySQL-8.0和MariaDB-10.2中可用:

select DATE(ts) as 'day', sum(ontime) as 'on time'
from (
  select status, lead(ts,1,ts) over w - ts as 'ontime'
  from (
    select unix_timestamp(ts) as ts, status
    from t
    order by ts
  ) x
  window w as (order by ts)
) y
where status=1
group by 'day'; 

答案 2 :(得分:0)

此查询适用于8.0之前的MySQL版本。它使用SELF JOIN查找给定heater off行的匹配heater on行。在不存在匹配行的地方,它使用当天结束时间或当前时间,以较低者为准。

SELECT DATE_FORMAT(t1.Date, '%d.%m') AS `day`,
       SUM(TIMESTAMPDIFF(MINUTE, t1.Date, COALESCE(t2.Date, LEAST(NOW(), DATE(t1.Date) + INTERVAL 1 DAY)))) AS Duration,
       MAX(t1.Total_heatings) AS Total_heatings
FROM thermostat t1
LEFT JOIN thermostat t2 ON t2.Status = 0 AND t2.Total_heatings = t1.Total_heatings AND DATE(t2.Date) = DATE(t1.Date)
WHERE t1.Status = 1 AND DATE(t1.Date) BETWEEN '2019-01-21' - INTERVAL 7 DAY AND '2019-01-21' 
GROUP BY `day`

输出:

day     Duration    Total_heatings
20.01   50          3
21.01   45          2

Demo on dbfiddle