You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL按天分组查询指定日期数据报错问题求助

解决精确日期的小时统计问题

首先,我们来拆解你遇到的两个核心问题,然后给出针对性的解决方案:

为什么最初的查询会返回所有月份的9号数据?

你的第一个查询用了HAVING ts = 09,但ts是%d-%m-%Y %H格式的完整时间字符串(比如09-10-2019 10),这个条件逻辑本身就有问题——它试图筛选出ts完全等于"09"的分组,但显然你的结果里并没有这样的分组,实际是因为模糊匹配拿到了所有日期日份为09的数据。

更关键的是:筛选原始数据应该用WHERE子句,而不是分组后的HAVING。HAVING是用来过滤分组结果的,不是用来限定原始数据范围的,这才导致你拿到了跨月份的结果。

为什么修改后的查询触发only_full_group_by错误?

你的第二个查询WHERE 09-10-2019是完全错误的SQL语法——MySQL会把09-10-2019解析成数学运算(09减10减2019,结果为-2019),相当于WHERE TRUE,会返回全表数据。同时,你在SELECT里同时放了非聚合列ts(来自record的格式化)和聚合函数COUNT(*),却没有指定GROUP BY,这违反了sql_mode=only_full_group_by的规则:这个模式要求聚合查询中,SELECT里的非聚合列必须出现在GROUP BY子句中,以此保证分组结果的确定性。


正确的解决方案

要统计2019-10-09当天每个小时的passed记录数,你需要:

  1. 先用WHERE精准筛选出该日期的所有数据(用日期范围比格式化字符串更高效,能用到record字段的索引)
  2. 再按小时分组统计

推荐的SQL语句:

SELECT DATE_FORMAT(record, '%d-%m-%Y %H') AS ts, COUNT(*) AS passed 
FROM counter 
WHERE record >= '2019-10-09 00:00:00' 
  AND record < '2019-10-10 00:00:00' -- 用小于次日0点的方式,包含当天所有时间点
GROUP BY ts;

另一种写法(日期字符串匹配,效率稍低):

如果你习惯用日期字符串匹配,也可以这样写,但这种写法无法利用record的索引,数据量大时性能会下降:

SELECT DATE_FORMAT(record, '%d-%m-%Y %H') AS ts, COUNT(*) AS passed 
FROM counter 
WHERE DATE_FORMAT(record, '%d-%m-%Y') = '09-10-2019'
GROUP BY ts;

这两种写法都会返回2019-10-09当天每个小时的统计数据,同时完全符合only_full_group_by的要求——因为ts作为分组依据,已经出现在了GROUP BY子句中。

内容的提问来源于stack exchange,提问作者Toribio Tio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:07