错误源于sql标准执行顺序:where→group by→having→select,聚合函数在分组后计算,而非聚合字段若未出现在group by中则无法确定取值;正确解法是使用子查询或窗口函数获取完整记录。

SELECT中混用聚合和非聚合字段直接报错
直接写 SELECT id, name, MAX(price) 会触发标准 SQL 错误,比如 MySQL 报 ERROR 1140: In aggregated query without GROUP BY,PostgreSQL 报 column "name" must appear in the GROUP BY clause。这不是数据库“不支持”,而是 SQL 执行顺序决定的:WHERE → GROUP BY → HAVING → SELECT,而 MAX() 是聚合阶段产物,id 和 name 却还处于未分组的原始行状态——数据库根本不知道该取哪一行的 id 和 name 来配这个最大值。
GROUP BY强行加字段也不解决问题
有人试过加 GROUP BY id, name,结果查出来一堆重复行,甚至每行 MAX(price) 都是它自己的 price。这是因为按 id 分组后,每组只有一行,MAX(price) 就等于那行自己的值,完全没起到“找全局最大”的作用。真要分组求极值,必须确保 GROUP BY 的字段逻辑上能代表一类数据(如 category),而不是把主键或唯一字段塞进去。
子查询和窗口函数才是正解
想拿到“价格最高那条记录的完整信息”,只有两种可靠路径:
- 子查询:用
WHERE price = (SELECT MAX(price) FROM products)—— 兼容所有版本,但可能扫描两次表; - 窗口函数:用
ROW_NUMBER() OVER (ORDER BY price DESC)或RANK()—— MySQL 8.0+ / PostgreSQL / SQL Server 支持,一次扫描,还能控制并列行为(比如只要一条就用ROW_NUMBER(),要全部并列就用RANK());
别试图在 SELECT 里硬凑字段,也别依赖 MySQL 旧版宽松模式下的随机返回——那不是功能,是隐患。
字符串或混合编码时MAX()“看起来失效”
如果字段是类似 'XHL001'、'XHL999' 这种字母+数字组合,MAX(code) 返回 'XHL999' 而不是真实最大编号,是因为它按字典序比较:'XHL999' > 'XHL1000' 成立。这时候 MAX() 没坏,只是语义不符合业务预期。修复方式是分离数字部分再转成数值比较,例如用 SUBSTRING(code, 4)::INT(PostgreSQL)或 CAST(SUBSTRING(code, 4) AS UNSIGNED)(MySQL),再套 MAX()。











