Mysql 按时间聚合
我想根据时间间隔聚合mysql数据库中的属性。以下是我的数据结构和一些示例数据: 事件表Mysql 按时间聚合,mysql,sql,performance,Mysql,Sql,Performance,我想根据时间间隔聚合mysql数据库中的属性。以下是我的数据结构和一些示例数据: 事件表 +----+---------------------+---------------------+ | id | start | end | +----+---------------------+---------------------+ | 1 | 2017-01-22 14:00:00 | 2017-01-22 17:00:00 | |
+----+---------------------+---------------------+
| id | start | end |
+----+---------------------+---------------------+
| 1 | 2017-01-22 14:00:00 | 2017-01-22 17:00:00 |
| 2 | 2017-01-22 15:00:00 | 2017-01-22 18:00:00 |
+----+---------------------+---------------------+
+----+----------+--------------+--------+
| id | event_id | person_count | status |
+----+----------+--------------+--------+
| 1 | 1 | 5 | 1 |
| 2 | 1 | 4 | 1 |
| 3 | 1 | 6 | 1 |
| 4 | 2 | 3 | 1 |
| 5 | 2 | 4 | 1 |
| 6 | 2 | 5 | 0 |
+----+----------+--------------+--------+
预订表
+----+---------------------+---------------------+
| id | start | end |
+----+---------------------+---------------------+
| 1 | 2017-01-22 14:00:00 | 2017-01-22 17:00:00 |
| 2 | 2017-01-22 15:00:00 | 2017-01-22 18:00:00 |
+----+---------------------+---------------------+
+----+----------+--------------+--------+
| id | event_id | person_count | status |
+----+----------+--------------+--------+
| 1 | 1 | 5 | 1 |
| 2 | 1 | 4 | 1 |
| 3 | 1 | 6 | 1 |
| 4 | 2 | 3 | 1 |
| 5 | 2 | 4 | 1 |
| 6 | 2 | 5 | 0 |
+----+----------+--------------+--------+
我正在寻找一种方法,以了解在预订状态为1的15分钟时间间隔内,有多少人(预订总数。人数)参加活动。因此,查询的输出应该如下所示:
+---------------------+--------------------+
| date | person_count_total |
+---------------------+--------------------+
| 2017-01-22 14:00:00 | 15 |
| 2017-01-22 14:15:00 | 15 |
| 2017-01-22 14:30:00 | 15 |
| 2017-01-22 14:45:00 | 15 |
| 2017-01-22 15:00:00 | 22 |
| 2017-01-22 15:15:00 | 22 |
| 2017-01-22 15:30:00 | 22 |
| 2017-01-22 15:45:00 | 22 |
| 2017-01-22 16:00:00 | 22 |
| 2017-01-22 16:15:00 | 22 |
| 2017-01-22 16:30:00 | 22 |
| 2017-01-22 16:45:00 | 22 |
| 2017-01-22 17:00:00 | 22 |
| 2017-01-22 17:15:00 | 7 |
| 2017-01-22 17:30:00 | 7 |
| 2017-01-22 17:45:00 | 7 |
| 2017-01-22 18:00:00 | 7 |
+---------------------+--------------------+
SELECT
t.date,
SUM(CASE
WHEN b.status = 1 THEN person_count
END) person_count_total
FROM
bookings b
INNER JOIN
events e ON b.event_id = e.id
INNER JOIN
(SELECT
(SELECT
MIN(start)
FROM
events) + INTERVAL 15 * (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) MINUTE AS Date
FROM
(SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS d
) t ON t.date BETWEEN e.start AND e.end
GROUP BY t.date
;
有没有办法只在mysql中实现这一点?当前的解决方案是在php应用程序的第一个开始和最后一个结束之间的15分钟间隔内循环。但是,由于这会创建大量数据点,而且性能不好,因为每个数据点都意味着一个查询。在日期之间生成行,然后与bookings表进行连接,如下所示:
+---------------------+--------------------+
| date | person_count_total |
+---------------------+--------------------+
| 2017-01-22 14:00:00 | 15 |
| 2017-01-22 14:15:00 | 15 |
| 2017-01-22 14:30:00 | 15 |
| 2017-01-22 14:45:00 | 15 |
| 2017-01-22 15:00:00 | 22 |
| 2017-01-22 15:15:00 | 22 |
| 2017-01-22 15:30:00 | 22 |
| 2017-01-22 15:45:00 | 22 |
| 2017-01-22 16:00:00 | 22 |
| 2017-01-22 16:15:00 | 22 |
| 2017-01-22 16:30:00 | 22 |
| 2017-01-22 16:45:00 | 22 |
| 2017-01-22 17:00:00 | 22 |
| 2017-01-22 17:15:00 | 7 |
| 2017-01-22 17:30:00 | 7 |
| 2017-01-22 17:45:00 | 7 |
| 2017-01-22 18:00:00 | 7 |
+---------------------+--------------------+
SELECT
t.date,
SUM(CASE
WHEN b.status = 1 THEN person_count
END) person_count_total
FROM
bookings b
INNER JOIN
events e ON b.event_id = e.id
INNER JOIN
(SELECT
(SELECT
MIN(start)
FROM
events) + INTERVAL 15 * (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) MINUTE AS Date
FROM
(SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS d
) t ON t.date BETWEEN e.start AND e.end
GROUP BY t.date
;
如果事件中最小日期和最大日期之间的差异较大,您可以简单地添加另一个交叉连接以适应更多范围,并添加10000*e.a
。。等等
+---------------------+--------------------+
| date | person_count_total |
+---------------------+--------------------+
| 2017-01-22 14:00:00 | 15 |
+---------------------+--------------------+
| 2017-01-22 14:15:00 | 15 |
+---------------------+--------------------+
| 2017-01-22 14:30:00 | 15 |
+---------------------+--------------------+
| 2017-01-22 14:45:00 | 15 |
+---------------------+--------------------+
| 2017-01-22 15:00:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 15:15:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 15:30:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 15:45:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 16:00:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 16:15:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 16:30:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 16:45:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 17:00:00 | 22 |
+---------------------+--------------------+
| 2017-01-22 17:15:00 | 7 |
+---------------------+--------------------+
| 2017-01-22 17:30:00 | 7 |
+---------------------+--------------------+
| 2017-01-22 17:45:00 | 7 |
+---------------------+--------------------+
| 2017-01-22 18:00:00 | 7 |
+---------------------+--------------------+
“这会创建很多数据点”。您不需要所有数据点的数据吗?如何避免这种情况?我的意思是,通过php脚本创建数据的成本很高。因为每个数据点意味着一个查询。17:00时的总和不正确,应该是22。因为当时1和2都在场@lasagneYou是对的。我编辑了这个问题