更新 MySQL 后,从 'sql_mode=only_full_group_by' 收到奇怪的 JOIN 错误
After updating MySQL, getting strange JOIN errors from 'sql_mode=only_full_group_by'
所以我刚更新到最新的 MySQL,我收到了这个错误:
Expression #1 of SELECT list is not in GROUP BY clause and contains
nonaggregated column 'stats.playtime.date' which is not
functionally dependent on columns in GROUP BY clause; this is
incompatible with sql_mode=only_full_group_by
我的table:
id int(255)
date datetime
我的查询:
SELECT DATE(date) + INTERVAL 1 DAY, COUNT(DISTINCT id)
FROM playtime
GROUP BY DATE(date)
它所做的只是告诉我有多少用户在特定日期首次加入,允许我在图表中显示此数据。
我不确定这个查询究竟有什么问题?我知道在这个新版本的 MySQL 中必须有新的语法规则,但我不确定如何在这个查询中遵循它们。有什么想法吗?
导致相同问题的第二个示例:
Table:
id int(11)
user varchar(255)
course varchar(255)
course_difficulty varchar(255)
time_taken int(255)
查询:
SELECT course, course_difficulty, time_taken
FROM minigame
WHERE user = 'abc'
GROUP BY course
ORDER BY time_taken LIMIT 50
COUNT(DISTINCT id)
是一个聚合函数,因此它允许出现在 select 子句中 group by
。但是 DATE(date) + INTERVAL 1 DAY
不是聚合函数,它没有出现在 group by
子句中,所以这是你出错的原因。
要解决此问题,您应该将未聚合的列添加到 group by
子句中,就像此查询中的
SELECT DATE(`date`) + INTERVAL 1 DAY, COUNT(DISTINCT id)
FROM playtime
GRUP BY DATE(`date`) + INTERVAL 1 DAY
有关 group by
和聚合函数的更多信息,您可以在 [此处] 找到。1
在第一个示例中,MySQL 优化器不够智能,无法识别表达式 DATE(date) + INTERVAL 1 DAY
在功能上依赖于 DATE(date)
。解决方法是将整个表达式包含在 GROUP BY 子句中。
在第二个例子中,MySQL 抱怨 SELECT 列表中不在 GROUP BY 子句中的非聚合,同样,因为它们在功能上不相关。
下面是一些示例 table 数据,说明了错误背后的基本原理:
id user course
-- ---- ------
11 fee win101
12 fi win101
13 fo win101
当我们尝试运行这个查询时:
SELECT t.course, t.user
FROM mytable t
GROUP BY t.course
return可以为 user
...fee、fi 或 fo 编辑三个可能的值。
如果我们使用聚合表达式代替列,MySQL 将允许查询 运行。在此示例中,我们可以使用 MIN(t.user) 或 MAX(t.user),而 MySQL 将分别为 return "fee" 或 "fo" .
MySQL 将 运行 这个查询:
SELECT t.course
, MIN(t.user) AS min_user
, MAX(t.user) AS max_user
, COUNT(1)
FROM mytable t
GROUP BY t.course
所以我刚更新到最新的 MySQL,我收到了这个错误:
Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'stats.playtime.date' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
我的table:
id int(255)
date datetime
我的查询:
SELECT DATE(date) + INTERVAL 1 DAY, COUNT(DISTINCT id)
FROM playtime
GROUP BY DATE(date)
它所做的只是告诉我有多少用户在特定日期首次加入,允许我在图表中显示此数据。
我不确定这个查询究竟有什么问题?我知道在这个新版本的 MySQL 中必须有新的语法规则,但我不确定如何在这个查询中遵循它们。有什么想法吗?
导致相同问题的第二个示例:
Table:
id int(11)
user varchar(255)
course varchar(255)
course_difficulty varchar(255)
time_taken int(255)
查询:
SELECT course, course_difficulty, time_taken
FROM minigame
WHERE user = 'abc'
GROUP BY course
ORDER BY time_taken LIMIT 50
COUNT(DISTINCT id)
是一个聚合函数,因此它允许出现在 select 子句中 group by
。但是 DATE(date) + INTERVAL 1 DAY
不是聚合函数,它没有出现在 group by
子句中,所以这是你出错的原因。
要解决此问题,您应该将未聚合的列添加到 group by
子句中,就像此查询中的
SELECT DATE(`date`) + INTERVAL 1 DAY, COUNT(DISTINCT id)
FROM playtime
GRUP BY DATE(`date`) + INTERVAL 1 DAY
有关 group by
和聚合函数的更多信息,您可以在 [此处] 找到。1
在第一个示例中,MySQL 优化器不够智能,无法识别表达式 DATE(date) + INTERVAL 1 DAY
在功能上依赖于 DATE(date)
。解决方法是将整个表达式包含在 GROUP BY 子句中。
在第二个例子中,MySQL 抱怨 SELECT 列表中不在 GROUP BY 子句中的非聚合,同样,因为它们在功能上不相关。
下面是一些示例 table 数据,说明了错误背后的基本原理:
id user course
-- ---- ------
11 fee win101
12 fi win101
13 fo win101
当我们尝试运行这个查询时:
SELECT t.course, t.user
FROM mytable t
GROUP BY t.course
return可以为 user
...fee、fi 或 fo 编辑三个可能的值。
MySQL 将允许查询 运行。在此示例中,我们可以使用 MIN(t.user) 或 MAX(t.user),而 MySQL 将分别为 return "fee" 或 "fo" .
MySQL 将 运行 这个查询:
SELECT t.course
, MIN(t.user) AS min_user
, MAX(t.user) AS max_user
, COUNT(1)
FROM mytable t
GROUP BY t.course