使用DISTINCT与MAX聚合函数的SQL语句报错原因及解决方法
问题解析
这条SQL语句报错的核心原因是违反了SQL的聚合函数使用规则:
- 当
SELECT子句同时包含普通列(SupplierId)和聚合函数(MAX(Price))时,必须通过GROUP BY子句对所有非聚合的普通列分组,数据库才能确定聚合函数的计算范围。你既没加GROUP BY,又想用DISTINCT替代分组逻辑,但DISTINCT只是对最终结果去重,无法解决聚合函数与普通列共存的语法冲突。 - 退一步说,就算语法能通过,这条语句的逻辑也不对:它会返回所有去重后的
SupplierId,每个都对应全局最高价格,这显然不是你要的“拥有最高Price的SupplierId”结果。
实现需求的示例方案
要获取拥有最高价格的SupplierId,返回一行两列的结果,以下是几种可行方案:
方案1:子查询匹配最高价格
SELECT SupplierId, Price FROM Products WHERE Price = (SELECT MAX(Price) FROM Products);
- 逻辑:先通过子查询拿到全局最高价格,再找出所有价格等于该值的商品对应的供应商。
- 注意:如果有多个供应商的商品价格同为最高,会返回多行;若要强制只返回一行,可根据数据库类型加限制(MySQL用
LIMIT 1,SQL Server用TOP 1,Oracle用WHERE ROWNUM <= 1)。
方案2:排序后取首行
SELECT SupplierId, Price FROM Products ORDER BY Price DESC LIMIT 1;
- 逻辑:将所有商品按价格降序排列,直接取第一行,就是价格最高的那一条。
- 注意:不同数据库的分页语法不同,需对应调整(比如SQL Server用
TOP 1,Oracle用ORDER BY Price DESC FETCH FIRST 1 ROW ONLY)。
方案3:窗口函数(适用于支持窗口函数的数据库)
如果需要保留所有价格并列最高的供应商,同时也能轻松取单行,可用窗口函数:
SELECT SupplierId, Price FROM ( SELECT SupplierId, Price, RANK() OVER(ORDER BY Price DESC) AS price_rank FROM Products ) AS ranked_data WHERE price_rank = 1 LIMIT 1;
- 逻辑:用
RANK()窗口函数给每个商品按价格排名,排名为1的就是价格最高的,最后可选限制行数。
内容的提问来源于stack exchange,提问作者Basir Touati
相关产品推荐
相关产品推荐

