max(distinct col) 语法错误,因 max 不支持 distinct 修饰符;正确做法是先用子查询或 cte 去重(select distinct),再在外层 group by 后使用 max。

SQL里MAX(DISTINCT col)不合法,别这么写
直接说结论:MAX(DISTINCT col) 在标准 SQL(包括 MySQL 8.0+、PostgreSQL、SQL Server)中**语法错误**,会报类似 ERROR 1064 或 syntax error near DISTINCT 的提示。不是你写错了括号,是语法根本不支持 —— MAX 函数本身不接受 DISTINCT 修饰符,和 COUNT 不同。
想统计“每个分组中去重后的最大值”,本质是先去重再聚合
你真正需要的,不是在 MAX 里塞 DISTINCT,而是:对每组数据先做去重(DISTINCT 或 GROUP BY),再取最大值。常见场景比如:一张订单表有重复的 user_id, amount 组合,你想知道每个用户「不同金额中的最高值」(即去重后取 max)。
正确做法是嵌套一层:
- 内层用
SELECT DISTINCT user_id, amount FROM orders消除重复行 - 外层按
user_id分组,用MAX(amount)
完整写法:
SELECT user_id, MAX(amount) AS max_unique_amount FROM (SELECT DISTINCT user_id, amount FROM orders) AS deduped GROUP BY user_id;
MySQL 8.0+ 可用窗口函数简化,但逻辑不变
如果只是想避免子查询,且数据库支持窗口函数(如 MySQL 8.0+、PostgreSQL),可以用 DENSE_RANK() 或 ROW_NUMBER() 配合过滤,但注意:这不比子查询更直观,反而容易绕晕。
例如,找每组去重后最大的那个值(仅取一行):
SELECT user_id, amount
FROM (
SELECT user_id, amount,
DENSE_RANK() OVER (PARTITION BY user_id ORDER BY amount DESC) AS rnk
FROM (SELECT DISTINCT user_id, amount FROM orders) AS d
) AS ranked
WHERE rnk = 1;
注意:这里仍需先 SELECT DISTINCT,否则窗口函数是在原始重复数据上排序,结果就错了。
别误用 GROUP_CONCAT + SUBSTRING_INDEX 代替去重
有人试过 GROUP_CONCAT(DISTINCT amount ORDER BY amount DESC) 再截取第一个,看似能绕开子查询,但隐患大:
-
GROUP_CONCAT有长度限制(默认 1024),超长会被截断,SUBSTRING_INDEX就取到错值 - 数值类型转字符串后排序可能出错(比如 '10'
- 无法处理
NULL值,GROUP_CONCAT默认忽略NULL,但你可能需要保留语义
这种写法看着短,实际不可靠,调试时容易卡在奇怪的数据上。
核心就一条:去重和聚合是两个独立动作,必须分步做;MAX 本身不负责去重,它只管当前输入集里的最大值。漏掉中间的 DISTINCT 这一步,结果一定不对。











