因此让我们充分了解一下。假设您有一个在本地主机上运行但在生产模式中不起作用的查询,这是因为在MySQL 5.7及以上版本中,默认启用 sql_mode=only_full_group_by
,它基本上是一种严格模式,防止您选择非聚合字段。
以下是查询(在本地工作但在生产模式中无效):
SELECT post.*, YEAR(created_at) as year
FROM post
GROUP BY year
SELECT post.id, YEAR(created_at) as year // This will generate an error since there are many ids
FROM post
GROUP BY year
要验证是否启用了sql_mode=only_full_group_by
,您应执行以下查询:
SELECT @@sql_mode; //localhost
输出: IGNORE_SPACE、STRICT_TRANS、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER、NO_ENGINE_SUBSTITUTION
(如果您看不到它,这意味着它被禁用了)
但是如果在生产模式下尝试,或者在某个地方出现应该激活错误的情况:
SELECT @@sql_mode; //production
输出: ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO...
我们需要关注的是 ONLY_FULL_GROUP_BY
。
否则,如果您正在使用phpMyAdmin,可以进入- > Variables
并搜索 sql_mode
让我们将之前的示例适应一下:
SELECT MIN(post.id), YEAR(created_at) as year //Here we are solving the problem with MIN()
FROM post
GROUP BY year
同样适用于MAX()
如果我们想要所有的ID,我们需要:
SELECT GROUP_CONCAT(post.id SEPARATOR ','), YEAR(created_at) as year
FROM post
GROUP BY year
或另一个新添加的功能:
SELECT ANY_VALUE(post.id), YEAR(created_at) as year
FROM post
GROUP BY year
⚠️ MariaDB 中不存在 ANY_VALUE。
如果你想获取所有字段,你可以使用相同的方法:
SELECT ANY_VALUE(post.id), ANY_VALUE(post.slug), ANY_VALUE(post.content) YEAR(created_at) as year
FROM post
GROUP BY year
❌ 要关闭sql_mode=only_full_group_by
,您需要执行以下查询:
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
抱歉篇幅有点长,希望能对您有所帮助。