SQL GROUP BY子句报错求助:按年份查询对应最高金额的品牌记录
问题重现
你的Practice表数据如下:
Year Brand Amount
2018 Apple 45000
2019 Apple 35000
2020 Apple 75000
2018 Samsung 15000
2019 Samsung 20000
2020 Samsung 95000
2018 Nokia 21000
2019 Nokia 17000
2020 Nokia 14000
你需要获取每年金额最高的品牌记录,期望输出:
Year Brand Amount
2018 Apple 45000
2019 Apple 35000
2020 Samsung 95000
但执行以下SQL时报错:
Select Year, Brand, Max(Amount)as HighestPrice from Practice Group by Year
错误信息:
"Column 'Practice.Brand' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."
错误原因
这个报错的核心逻辑是:当你用GROUP BY Year时,数据库会将同一年的所有行合并成一个分组。此时你在SELECT里指定Brand,数据库无法确定应该返回该年份下哪一个品牌——因为每个年份分组里有多个不同的Brand值,既没有用聚合函数(比如MAX(Brand),但这不是你需要的对应最高金额的品牌),也没有把Brand加入GROUP BY(那样会变成按Year+Brand分组,不符合你的需求)。
解决方案
这里提供两种常用且可靠的方法:
方法1:使用窗口函数(推荐,简洁灵活)
利用ROW_NUMBER()窗口函数对每个年份的记录按金额降序排名,然后取排名为1的记录:
WITH RankedRecords AS ( SELECT Year, Brand, Amount, -- 按Year分区,每个分区内按Amount降序排名 ROW_NUMBER() OVER (PARTITION BY Year ORDER BY Amount DESC) AS RankNum FROM Practice ) SELECT Year, Brand, Amount FROM RankedRecords WHERE RankNum = 1;
- 如果你需要处理同年多个品牌金额并列最高的情况,可以把
ROW_NUMBER()换成RANK()或DENSE_RANK(),这样会返回所有并列第一的记录。
方法2:子查询关联
先通过子查询获取每年的最高金额,再关联原表找到对应的品牌记录:
SELECT p.Year, p.Brand, p.Amount FROM Practice p INNER JOIN ( -- 先得到每年的最高金额 SELECT Year, MAX(Amount) AS MaxAmount FROM Practice GROUP BY Year ) YearMax ON p.Year = YearMax.Year AND p.Amount = YearMax.MaxAmount;
- 这种方法同样会返回同年金额并列最高的所有记录,适合不需要窗口函数的旧版SQL环境。
内容的提问来源于stack exchange,提问作者user18665

