所以让我们充分理解,假设您有一个在 localhost 下工作但在生产模式下不工作的查询,这是因为在MySQL 5.7 and above 他们决定默认激活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', ''));
对小说感到抱歉,希望对您有所帮助。