MysQL - 汇总日期时间行拆分
MysQL - Aggregate Datetime Row splitting
有人能帮我解决下面的 MySQL 挑战吗?
报告的数据在所选日期内按小时细分。如果 device_table 表示设备在几个小时内不可用,它将在每个小时内报告,例如如果设备按如下方式保存设备记录,
select * from device_table
+----+---------------------+---------------------+--------+
| id | Start_timestamp | End_timestamp | STATUS |
+----+---------------------+---------------------+--------+
| 1 | 28/11/2014 13:26:25 | 28/11/2014 13:36:22 | UP |
| 2 | 28/11/2014 13:36:23 | 28/11/2014 14:06:27 | DN |
| 3 | 28/11/2014 14:06:28 | 28/11/2014 14:06:28 | UP |
| 4 | 28/11/2014 14:06:29 | 28/11/2014 14:11:26 | DN |
+----+---------------------+---------------------+--------+
然后设备将在 13:00 和 14:00 小时内报告为不可用,因为第二条记录在这两个小时内,最后一条记录也在小时 14:00 内。
如何拆分记录并形成查询来实现以上并根据他们的时间统计上下设备?
如果设备从 2014 年 11 月 28 日 13:36:23 到 2014 年 11 月 28 日 14:06:27 出现故障,那么我的查询应该计算该设备在 2 小时停机,即 13:36:23 和 14:06:27,而且如果我的设备在 28/11/2014 13:36:23 t0 28/11/2014 13:46:27 停机,那么我的设备应该仅报告为停机一小时,即 13.00 小时
查询的输出应该如下所示
+-------+----+-------+-----------------+
| Hours | up | down | total(UP+DOWN) |
+-------+----+-------+-----------------+
| 00.00 | 1 | 0 | 1 |
| 01.00 | 1 | 1 | 2 |
| 02.00 | 0 | 0 | 0 |
| : : | | | |
| : : | | | |
| 23:00 | 0 | 1 | 1 |
+-------+----+-------+-----------------+
试试下面的查询。
SELECT `tab_a`.`ID`, `tab_a`.`start-date-time`, `tab_a`.`end-date-time`,
`tab_a`.`timediff`, `tab_a`.`status`
FROM `tab_a`
INNER JOIN (
SELECT `tens`.`count` * 10 + `ones`.`count` AS `num-hours`
FROM (
SELECT 1 AS `count` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION
SELECT 9 UNION SELECT 10
) `ones`
CROSS JOIN (
SELECT 1 AS `count` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION
SELECT 9 UNION SELECT 10
) `tens`
) `increment`
ON (
`tab_a`.`start-date-time` + INTERVAL `increment`.`num-hours` HOUR
< `tab_a`.`end-date-time`
)
已添加修改问题的解决方案
以下查询应该可以满足您对前 7 天时间的要求。
SELECT `dates`.`date`, `times`.`hour`,
CASE WHEN (COALESCE(COUNT(`device_up`.`ID`), 0) > 0) THEN 1 ELSE 0 END AS `up`,
CASE WHEN (COALESCE(COUNT(`device_dn`.`ID`), 0) > 0) THEN 1 ELSE 0 END AS `down`,
CASE WHEN (COALESCE(COUNT(`device_up`.`ID`), 0) > 0) THEN 1 ELSE 0 END + CASE WHEN (COALESCE(COUNT(`device_dn`.`ID`), 0) > 0) THEN 1 ELSE 0 END AS `up-down`
FROM (
SELECT DATE_FORMAT(NOW() - INTERVAL `count` DAY, '%Y-%m-%d') AS `date`
FROM (
SELECT 1 AS `count` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7
) `ones`
) `dates`
CROSS JOIN (
SELECT `sixes`.`count` * 4 + `fours`.`count` AS `hour`
FROM (
SELECT 0 AS `count` UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION
SELECT 4 UNION SELECT 5
) `sixes`
CROSS JOIN (
SELECT 0 AS `count` UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
) `fours`
) `times`
LEFT JOIN (
SELECT `ID`, `Start_timestamp`, `End_timestamp`
FROM `device_table`
WHERE (`status` = 'UP')
) `device_up`
ON (
(`device_up`.`Start_timestamp` < `dates`.`date` + INTERVAL `times`.`hour` + 1 HOUR)
AND (`device_up`.`End_timestamp` > `dates`.`date` + INTERVAL `times`.`hour` HOUR)
)
LEFT JOIN (
SELECT `ID`, `Start_timestamp`, `End_timestamp`
FROM `device_table`
WHERE (`status` = 'DN')
) `device_dn`
ON (
(`device_dn`.`Start_timestamp` < `dates`.`date` + INTERVAL `times`.`hour` + 1 HOUR)
AND (`device_dn`.`End_timestamp` > `dates`.`date` + INTERVAL `times`.`hour` HOUR)
)
GROUP BY `dates`.`date`, `times`.`hour`
ORDER BY `dates`.`date`, `times`.`hour`
你的时差上限是多少?
select *
from tab_a as t,
(select 0 as n union all select 1 union all select 2...) as duplicator
where t.timediff < duplicator.n
有人能帮我解决下面的 MySQL 挑战吗?
报告的数据在所选日期内按小时细分。如果 device_table 表示设备在几个小时内不可用,它将在每个小时内报告,例如如果设备按如下方式保存设备记录,
select * from device_table
+----+---------------------+---------------------+--------+
| id | Start_timestamp | End_timestamp | STATUS |
+----+---------------------+---------------------+--------+
| 1 | 28/11/2014 13:26:25 | 28/11/2014 13:36:22 | UP |
| 2 | 28/11/2014 13:36:23 | 28/11/2014 14:06:27 | DN |
| 3 | 28/11/2014 14:06:28 | 28/11/2014 14:06:28 | UP |
| 4 | 28/11/2014 14:06:29 | 28/11/2014 14:11:26 | DN |
+----+---------------------+---------------------+--------+
然后设备将在 13:00 和 14:00 小时内报告为不可用,因为第二条记录在这两个小时内,最后一条记录也在小时 14:00 内。
如何拆分记录并形成查询来实现以上并根据他们的时间统计上下设备?
如果设备从 2014 年 11 月 28 日 13:36:23 到 2014 年 11 月 28 日 14:06:27 出现故障,那么我的查询应该计算该设备在 2 小时停机,即 13:36:23 和 14:06:27,而且如果我的设备在 28/11/2014 13:36:23 t0 28/11/2014 13:46:27 停机,那么我的设备应该仅报告为停机一小时,即 13.00 小时
查询的输出应该如下所示
+-------+----+-------+-----------------+
| Hours | up | down | total(UP+DOWN) |
+-------+----+-------+-----------------+
| 00.00 | 1 | 0 | 1 |
| 01.00 | 1 | 1 | 2 |
| 02.00 | 0 | 0 | 0 |
| : : | | | |
| : : | | | |
| 23:00 | 0 | 1 | 1 |
+-------+----+-------+-----------------+
试试下面的查询。
SELECT `tab_a`.`ID`, `tab_a`.`start-date-time`, `tab_a`.`end-date-time`,
`tab_a`.`timediff`, `tab_a`.`status`
FROM `tab_a`
INNER JOIN (
SELECT `tens`.`count` * 10 + `ones`.`count` AS `num-hours`
FROM (
SELECT 1 AS `count` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION
SELECT 9 UNION SELECT 10
) `ones`
CROSS JOIN (
SELECT 1 AS `count` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION
SELECT 9 UNION SELECT 10
) `tens`
) `increment`
ON (
`tab_a`.`start-date-time` + INTERVAL `increment`.`num-hours` HOUR
< `tab_a`.`end-date-time`
)
已添加修改问题的解决方案
以下查询应该可以满足您对前 7 天时间的要求。
SELECT `dates`.`date`, `times`.`hour`,
CASE WHEN (COALESCE(COUNT(`device_up`.`ID`), 0) > 0) THEN 1 ELSE 0 END AS `up`,
CASE WHEN (COALESCE(COUNT(`device_dn`.`ID`), 0) > 0) THEN 1 ELSE 0 END AS `down`,
CASE WHEN (COALESCE(COUNT(`device_up`.`ID`), 0) > 0) THEN 1 ELSE 0 END + CASE WHEN (COALESCE(COUNT(`device_dn`.`ID`), 0) > 0) THEN 1 ELSE 0 END AS `up-down`
FROM (
SELECT DATE_FORMAT(NOW() - INTERVAL `count` DAY, '%Y-%m-%d') AS `date`
FROM (
SELECT 1 AS `count` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION
SELECT 5 UNION SELECT 6 UNION SELECT 7
) `ones`
) `dates`
CROSS JOIN (
SELECT `sixes`.`count` * 4 + `fours`.`count` AS `hour`
FROM (
SELECT 0 AS `count` UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION
SELECT 4 UNION SELECT 5
) `sixes`
CROSS JOIN (
SELECT 0 AS `count` UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
) `fours`
) `times`
LEFT JOIN (
SELECT `ID`, `Start_timestamp`, `End_timestamp`
FROM `device_table`
WHERE (`status` = 'UP')
) `device_up`
ON (
(`device_up`.`Start_timestamp` < `dates`.`date` + INTERVAL `times`.`hour` + 1 HOUR)
AND (`device_up`.`End_timestamp` > `dates`.`date` + INTERVAL `times`.`hour` HOUR)
)
LEFT JOIN (
SELECT `ID`, `Start_timestamp`, `End_timestamp`
FROM `device_table`
WHERE (`status` = 'DN')
) `device_dn`
ON (
(`device_dn`.`Start_timestamp` < `dates`.`date` + INTERVAL `times`.`hour` + 1 HOUR)
AND (`device_dn`.`End_timestamp` > `dates`.`date` + INTERVAL `times`.`hour` HOUR)
)
GROUP BY `dates`.`date`, `times`.`hour`
ORDER BY `dates`.`date`, `times`.`hour`
你的时差上限是多少?
select *
from tab_a as t,
(select 0 as n union all select 1 union all select 2...) as duplicator
where t.timediff < duplicator.n