迭代列以显示时间之间的计数

时间:2019-02-05 16:46:04

标签: mysql

我正在尝试从MySQL生成一个结果集,该结果集将向我显示行之间的行数,该行在一天的开始和结束之间的时间间隔,因此我可以得出房间利用率,例如从8.30小时开始直到21.30。

准备该过程的源数据保存在以下格式的表中(即会话的开始和结束时间)

我可以编写一些PHP来进行多次迭代,以尝试确定是否可以直接在MySQL中直接完成。

源表(样本数据)

id  start_time            end_time               hostname          room
1   2018-10-19 16:28:37   2018-10-22 11:44:43    DESKTOP-FMVT2MJ   Room A

所需的示例输出:

          8.30 9.30 10.30 11.30 ...
 Room A   0    3    4     2
 Room B   0    0    0     5

1 个答案:

答案 0 :(得分:1)

在MySQL中进行透视是很困难的,因为您必须为该列的每个实例创建存储桶,这使得它相当长且重复。但是,如果您真的想在MySQL中而不是在php中执行此操作,那么它将起作用:

TEST表结构:

id  start_time          end_time            hostname room
1   2019-01-01 06:30:00 2019-01-01 07:30:00 test1    Room A
2   2019-01-01 07:00:00 2019-01-01 07:30:00 test2    Room A
3   2019-01-01 08:00:00 2019-01-01 09:00:00 test1    Room B
4   2019-01-01 06:00:00 2019-01-01 09:00:00 test3    Room C
5   2019-01-01 06:45:00 2019-01-01 07:45:00 test2    Room B
6   2019-01-01 07:15:00 2019-01-01 08:55:00 test1    Room B
7   2019-01-01 08:15:00 2019-01-01 09:30:00 test2    Room C
8   2019-01-01 06:00:00 2019-01-01 18:30:00 test3    Room A

查询:

SELECT
    room,
    SUM(IF(6 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '6Hr',
    SUM(IF(7 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '7Hr',
    SUM(IF(8 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '8Hr',
    SUM(IF(9 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '9Hr',
    SUM(IF(10 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '10Hr',
    SUM(IF(11 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '11Hr',
    SUM(IF(12 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '12Hr',
    SUM(IF(13 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '13Hr',
    SUM(IF(14 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '14Hr',
    SUM(IF(15 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '15Hr',
    SUM(IF(16 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '16Hr',
    SUM(IF(17 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '17Hr',
    SUM(IF(18 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '18Hr',
    SUM(IF(19 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '19Hr',
    SUM(IF(20 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '20Hr',
    SUM(IF(21 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '21Hr',
    SUM(IF(22 BETWEEN DATE_FORMAT(start_time,'%H') AND DATE_FORMAT(DATE_SUB(end_time,INTERVAL 1 SECOND),'%H'),1,0)) AS '22Hr'
FROM
    TEST
WHERE
    DATE(start_time) = '2019-01-01'
AND DATE(end_time) = '2019-01-01'
GROUP BY room

结果:

room    6Hr 7Hr 8Hr 9Hr 10Hr 11Hr 12Hr 13Hr 14Hr 15Hr 16Hr 17Hr 18Hr 19Hr 20Hr 21Hr 22Hr
Room A  2   3   1   1   1    1    1    1    1    1    1    1    1    0    0    0    0
Room B  1   2   2   0   0    0    0    0    0    0    0    0    0    0    0    0    0
Room C  1   1   2   1   0    0    0    0    0    0    0    0    0    0    0    0    0

这假设每个房间start_time在开始的同一天都有一个end_time

我使用了IF语句来确定特定的会议行是否为BETWEEN特定时间,每个时段每个小时。对于end_time,如果它的结束时间是例如09:00:00,则您不希望将其计入9Hr存储桶中(因为BETWEEN包含结束范围),所以我DATE_SUB花费了一秒钟的时间,因此它停留在8Hr存储桶中。由于这些必须非常严格,因此如果一行在09:00:01结束,它将计入9Hr存储桶中。可以根据您的喜好修改此逻辑。