MySQL 日期分组 select 语句
MySQL date grouping select statement
我有一个 MySQL 8.0.23 table 具有以下架构的调用事件:
eventUID - 整数 NOT NULL
camtimestamp - MySQL 日期时间戳
方向 - 字符串 - “In”或“Out”
propUID - 整数
在单个 SELECT 语句中,我试图按小时确定过去 24 小时内有多少辆汽车“进站”和多少辆“出站”。这是我正在尝试的(还没有内置 24 小时限制)。
select camtimestamp,count(*) from events where direction ="In" and propUID = 7 group by year(camtimestamp),month(camtimestamp),day(camtimestamp),hour(camtimestamp);
这是我得到的示例。
2022-02-14 22:02:40 38
2022-02-14 21:56:56 15
2022-02-14 20:55:30 47
2022-02-14 19:59:18 51
2022-02-14 18:59:50 36
2022-02-14 17:52:04 10
2022-02-14 16:58:01 16
2022-02-14 15:59:00 36
2022-02-14 14:58:52 44
我还有一个名为 datehourlist 的 table,我可以用它加入我的 SELECT。
示例数据:
2019-05-01 00:00:00
2019-05-01 01:00:00
2019-05-01 02:00:00
2019-05-01 03:00:00
2019-05-01 04:00:00
2019-05-01 05:00:00
2019-05-01 06:00:00
2019-05-01 07:00:00
2019-05-01 08:00:00
还有:
mysql> select min(datehour) from datehourlist;
+---------------------+
| min(datehour) |
+---------------------+
| 2019-05-01 00:00:00 |
+---------------------+
1 row in set (0.02 sec)
mysql> select max(datehour) from datehourlist;
+---------------------+
| max(datehour) |
+---------------------+
| 2040-12-31 00:00:00 |
+---------------------+
1 row in set (0.02 sec)
datehourlist 包含从 2019 年 5 月 1 日到 2040 年 12 月 31 日的每个小时。
这是我真正想要的示例:
下面的第 1 列是一个四舍五入的分组时间戳(对比上面的第 1 列是一个非四舍五入的实际时间戳)
如果没有来自该小时的数据,则下面的第 1 列不会跳过该小时。
下面的第 2 列是该小时的“在”计数。
下方第 3 列是该小时的“外出”次数。
2019-05-02 06:00:00 5 10
2019-05-02 07:00:00 127 10
2019-05-02 08:00:00 0 0
2019-05-02 09:00:00 115 10
2019-05-02 10:00:00 71 10
2019-05-02 11:00:00 147 10
2019-05-02 12:00:00 140 10
我应该使用什么 SELECT 语句来获得我需要的输出?
此外,我将如何优化 SELECT 语句?
在事件中,我有 50 万个事件并且每天增长 100 个。
预先感谢您的帮助。
感谢您这么快就给出了很好的解决方案。
SELECT dhl.datehour datehour,
COALESCE(SUM(ev.direction = 'In'), 0) `In`,
COALESCE(SUM(ev.direction = 'Out'), 0) `Out`
FROM datehourlist dhl
LEFT JOIN events ev
ON DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00') = dhl.datehour
WHERE ev.camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND ev.camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND ev.propUID = 7
GROUP BY dhl.datehour;
首先,我们需要一个 trunc_to_hour() 函数,它接受任意 DATETIME
或 TIMESTAMP
值并返回时间到了。就是这个。
DATE_FORMAT(camtimestamp, '%Y-%m-%d %H:00:00')
其次,我们需要一个可以处理最近 24 小时的 WHERE 表达式。就是这个。
WHERE camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
对于示例时间戳 2021-03-14 16:04:30
这给出了以下内容。
WHERE camtimestamp >= `2021-03-13 16:00:00`
AND camtimestamp < '2021-03-14 16:00:00`
即选择最近24个完整时钟小时的记录。如果您希望时间为最新,您可能需要调整此 WHERE 表达式。
第三,我们需要条件求和(对于 In 和 Out)。
当 direction
是 In
时表达式 direction = 'In'
给出 1
,当 direction
是其他字符串时 0
(如 Out
),如果 direction
本身为 NULL,则为 NULL。所以
SUM(direction='In')
计算满足该标准的行数。
第四,当SUM为空时,我们要显示零。像这样。
COALESCE(SUM(direction='In'),0)
第五,我们可以像这样把它放在一起:
SELECT DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00') datehour,
COALESCE(SUM(ev.direction = 'In'), 0) `In`,
COALESCE(SUM(ev.direction = 'Out'), 0) `Out`
FROM events ev
WHERE ev.camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND ev.camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND ev.propUID = 7
GROUP BY DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00')
这给了你你的结果集。但如果没有这些时间的记录,它仍然可能会丢失一些时间。
那么,第六,我们可以像这样将其添加到您的 pre-existing 每小时日历 table 中:
SELECT dhl.datehour datehour,
COALESCE(SUM(ev.direction = 'In'), 0) `In`,
COALESCE(SUM(ev.direction = 'Out'), 0) `Out`
FROM datehourlist dhl
LEFT JOIN events ev
ON DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00') = dhl.datehour
WHERE ev.camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND ev.camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND ev.propUID = 7
GROUP BY dhl.datehour
应该就可以了。 (未调试。)
我有一个 MySQL 8.0.23 table 具有以下架构的调用事件:
eventUID - 整数 NOT NULL
camtimestamp - MySQL 日期时间戳
方向 - 字符串 - “In”或“Out”
propUID - 整数
在单个 SELECT 语句中,我试图按小时确定过去 24 小时内有多少辆汽车“进站”和多少辆“出站”。这是我正在尝试的(还没有内置 24 小时限制)。
select camtimestamp,count(*) from events where direction ="In" and propUID = 7 group by year(camtimestamp),month(camtimestamp),day(camtimestamp),hour(camtimestamp);
这是我得到的示例。
2022-02-14 22:02:40 38
2022-02-14 21:56:56 15
2022-02-14 20:55:30 47
2022-02-14 19:59:18 51
2022-02-14 18:59:50 36
2022-02-14 17:52:04 10
2022-02-14 16:58:01 16
2022-02-14 15:59:00 36
2022-02-14 14:58:52 44
我还有一个名为 datehourlist 的 table,我可以用它加入我的 SELECT。
示例数据:
2019-05-01 00:00:00
2019-05-01 01:00:00
2019-05-01 02:00:00
2019-05-01 03:00:00
2019-05-01 04:00:00
2019-05-01 05:00:00
2019-05-01 06:00:00
2019-05-01 07:00:00
2019-05-01 08:00:00
还有:
mysql> select min(datehour) from datehourlist;
+---------------------+
| min(datehour) |
+---------------------+
| 2019-05-01 00:00:00 |
+---------------------+
1 row in set (0.02 sec)
mysql> select max(datehour) from datehourlist;
+---------------------+
| max(datehour) |
+---------------------+
| 2040-12-31 00:00:00 |
+---------------------+
1 row in set (0.02 sec)
datehourlist 包含从 2019 年 5 月 1 日到 2040 年 12 月 31 日的每个小时。
这是我真正想要的示例:
下面的第 1 列是一个四舍五入的分组时间戳(对比上面的第 1 列是一个非四舍五入的实际时间戳)
如果没有来自该小时的数据,则下面的第 1 列不会跳过该小时。
下面的第 2 列是该小时的“在”计数。
下方第 3 列是该小时的“外出”次数。
2019-05-02 06:00:00 5 10
2019-05-02 07:00:00 127 10
2019-05-02 08:00:00 0 0
2019-05-02 09:00:00 115 10
2019-05-02 10:00:00 71 10
2019-05-02 11:00:00 147 10
2019-05-02 12:00:00 140 10
我应该使用什么 SELECT 语句来获得我需要的输出?
此外,我将如何优化 SELECT 语句?
在事件中,我有 50 万个事件并且每天增长 100 个。
预先感谢您的帮助。
感谢您这么快就给出了很好的解决方案。
SELECT dhl.datehour datehour,
COALESCE(SUM(ev.direction = 'In'), 0) `In`,
COALESCE(SUM(ev.direction = 'Out'), 0) `Out`
FROM datehourlist dhl
LEFT JOIN events ev
ON DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00') = dhl.datehour
WHERE ev.camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND ev.camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND ev.propUID = 7
GROUP BY dhl.datehour;
首先,我们需要一个 trunc_to_hour() 函数,它接受任意 DATETIME
或 TIMESTAMP
值并返回时间到了。就是这个。
DATE_FORMAT(camtimestamp, '%Y-%m-%d %H:00:00')
其次,我们需要一个可以处理最近 24 小时的 WHERE 表达式。就是这个。
WHERE camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
对于示例时间戳 2021-03-14 16:04:30
这给出了以下内容。
WHERE camtimestamp >= `2021-03-13 16:00:00`
AND camtimestamp < '2021-03-14 16:00:00`
即选择最近24个完整时钟小时的记录。如果您希望时间为最新,您可能需要调整此 WHERE 表达式。
第三,我们需要条件求和(对于 In 和 Out)。
当 direction
是 In
时表达式 direction = 'In'
给出 1
,当 direction
是其他字符串时 0
(如 Out
),如果 direction
本身为 NULL,则为 NULL。所以
SUM(direction='In')
计算满足该标准的行数。
第四,当SUM为空时,我们要显示零。像这样。
COALESCE(SUM(direction='In'),0)
第五,我们可以像这样把它放在一起:
SELECT DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00') datehour,
COALESCE(SUM(ev.direction = 'In'), 0) `In`,
COALESCE(SUM(ev.direction = 'Out'), 0) `Out`
FROM events ev
WHERE ev.camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND ev.camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND ev.propUID = 7
GROUP BY DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00')
这给了你你的结果集。但如果没有这些时间的记录,它仍然可能会丢失一些时间。
那么,第六,我们可以像这样将其添加到您的 pre-existing 每小时日历 table 中:
SELECT dhl.datehour datehour,
COALESCE(SUM(ev.direction = 'In'), 0) `In`,
COALESCE(SUM(ev.direction = 'Out'), 0) `Out`
FROM datehourlist dhl
LEFT JOIN events ev
ON DATE_FORMAT(ev.camtimestamp, '%Y-%m-%d %H:00:00') = dhl.datehour
WHERE ev.camtimestamp >= DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 24 HOUR
AND ev.camtimestamp < DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND ev.propUID = 7
GROUP BY dhl.datehour
应该就可以了。 (未调试。)