将子选项与日历表连接以填充缺少数据的天数

时间:2014-10-30 19:59:51

标签: mysql join calendar timestamp

我有一个包含设备启动/停止时间和设备标识符的表。我最终想要实现的结果是在指定范围内的每一天的给定时间段(以秒为单位)内对每日运行时间和运行时间进行分组。

我想要实现的目标:

time        ADduration  PPduration
2014-07-18  0.66        0.66
2014-07-20  0.53        0.30

数据库的一部分:

CREATE TABLE ac 
(
 startTime datetime, 
 endTime datetime,
 status tinyint(4), 
 device varchar(5)
);

INSERT INTO ac
(startTime, endTime, status, device)
VALUES
('2014-07-18 05:00:00','2014-07-18 05:04:00',1,'PWR6'),
('2014-07-18 05:54:00','2014-07-18 06:06:00',1,'PWR8'),
('2014-07-18 06:57:00','2014-07-18 07:11:00',1,'PWR8'),
('2014-07-18 10:01:00','2014-07-18 10:15:00',1,'PWR8'),
('2014-07-20 22:37:00','2014-07-20 22:55:00',1,'PWR8'),
('2014-07-20 22:38:00','2014-07-20 22:40:00',1,'PWR6'),
('2014-07-20 23:07:00','2014-07-20 23:12:00',1,'PWR6'),
('2014-07-20 23:12:00','2014-07-20 23:26:00',1,'PWR8'),
('2014-07-20 23:39:00','2014-07-20 23:44:00',1,'PWR6');

我已经阅读了'日历表'技巧,所以我的数据库中也有一个日历表。

CREATE TABLE calendar (calendar_date date);

INSERT INTO calendar (calendar_date)
VALUES
('2014-07-18'),
('2014-07-19'),
('2014-07-20');

我已经构建了几个几乎实现我正在寻找的查询,但我似乎无法将它们全部包装在一起。

此查询可以获取与我的数据表连接的日历,以确保我的结果中仍然显示没有任何数据的日期,但我认为我需要一个子选择,以确保只包含一个设备。

SELECT calendar.calendar_date as DATE, IFNULL(truncate(sum(TIMESTAMPDIFF(second, startTime,            stopTime))/60/60,2),0) AS duration
FROM `ac` RIGHT JOIN calendar ON (DATE(startTime) = calendar.calendar_date)
WHERE calendar.calendar_date BETWEEN '2014-07-18' AND '2014-07-20'
GROUP BY DATE

结果:

DATE, duration
2014-07-18, 0.73
2014-07-19, 0.00
2014-07-20, 0.73

这与我来的一样接近,但它并不包括指定范围内的所有日期,并且当第二个选择中的时间选择器将结果限制为0行时,选择范围越大未能包含给定数据的日期。

SELECT AllDay.time, AllDay.duration as ADduration, PP.duration as PPduration 
FROM (
    SELECT date(startTime) as time, truncate(sum(TIMESTAMPDIFF(second, startTime, stopTime))/60/60,2) as duration 
    FROM `ac` 
    WHERE startTime BETWEEN '2014-07-18' AND '2014-07-22' 
    AND device = 'PWR8' 
    GROUP BY date(startTime)) AllDay 
INNER JOIN (
    SELECT date(startTime) as time, truncate(sum(TIMESTAMPDIFF(second, startTime, stopTime))/60/60,2) as duration 
    FROM `ac` 
    WHERE startTime BETWEEN '2014-07-18' AND '2014-07-22' 
    AND time(startTime) BETWEEN '03:00:00' AND '23:00:00' 
    AND device = 'PWR8' 
    GROUP BY date(startTime)) PP 
ON AllDay.time = PP.time

结果:

time, ADduration, PPduration
2014-07-18, 0.66, 0.66
2014-07-20, 0.53, 0.30

0 个答案:

没有答案