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

sql_mode=only_full_group_by导致GROUP BY查询报错及分组需求问询

解决MySQL GROUP BY与only_full_group_by模式冲突的问题

这个问题我之前踩过坑!MySQL的only_full_group_by严格模式会强制要求:SELECT列表中的所有非聚合列必须出现在GROUP BY子句中,否则就会抛出你遇到的那个错误。你的需求是每个唯一weight对应一条记录,下面给你几种靠谱的解决思路:

方法1:使用聚合函数指定要返回的组内记录

如果你的需求是取每组中id最小(或最大)的那条记录,可以用MIN()/MAX()聚合函数锁定id,再关联原表获取对应的name:

SELECT 
    r.id, 
    r.name, 
    r.weight
FROM resource r
JOIN (
    SELECT 
        MIN(id) AS min_id, 
        weight 
    FROM resource 
    JOIN inventory ON resource.weight = inventory.weight 
    WHERE inventory.key = ? 
    GROUP BY weight
) AS grouped ON r.id = grouped.min_id;

这个写法先通过子查询按weight分组,拿到每组的最小id,再关联原表获取对应的name和weight,结果完全可控。

方法2:用窗口函数灵活选择组内记录(推荐)

如果你需要更灵活的规则(比如按id排序取第一条/最后一条,或者按其他字段排序),窗口函数ROW_NUMBER()是最优解:

WITH ranked_resources AS (
    SELECT 
        resource.id, 
        resource.name, 
        resource.weight,
        -- 按weight分组,每组内按id升序编号(取第一条),如果要取最后一条改成ORDER BY id DESC
        ROW_NUMBER() OVER (PARTITION BY resource.weight ORDER BY resource.id ASC) AS rn
    FROM resource 
    JOIN inventory ON resource.weight = inventory.weight 
    WHERE inventory.key = ?
)
SELECT id, name, weight
FROM ranked_resources
WHERE rn = 1;
  • PARTITION BY resource.weight:把数据按weight拆分成独立的组
  • ROW_NUMBER() OVER (...):给每组内的行按指定规则编号
  • 最后筛选rn=1的行,就是每组的第一条记录

方法3:临时关闭only_full_group_by模式(不推荐)

虽然可以临时关闭这个严格模式,但非常不建议——这会违反SQL标准,返回的id和name是随机的,结果不可控:

-- 临时关闭当前会话的only_full_group_by模式
SET sql_mode = (SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));

-- 再执行你的原查询(结果可能随机)
SELECT resource.id, resource.name, resource.weight FROM resource JOIN inventory ON resource.weight = inventory.weight WHERE inventory.key = ? GROUP BY resource.weight;

这种方法只适合临时测试,生产环境绝对不要用!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:26:35