如何用SQL查询每日最大totalcst值?语句优化求助
解决每日最大totalcst值的获取问题
看起来你之前的思路偏了,咱们先拆解下问题:你要的是每天中totalcst最大的那条记录(或者每日的最大totalcst值),但你原来的SQL用GROUP BY date, pid会把每个日期下的不同pid都单独分组计算,自然会返回所有分组的结果,这就不是你要的每日全局最大了。
问题出在哪?
你的原SQL:
select date,pid,max(quan*cst), totalcst from dbo.test1 group by date, pid
这里有两个核心问题:
GROUP BY date, pid是按「日期+pid」分组,所以会输出每个日期下每个pid的最大quan*cst,而不是整个日期里的最大值。- 你直接选了
totalcst,但它既不在GROUP BY里,也没被聚合函数处理,这在严格的SQL模式下会报错(比如SQL Server的SET ANSI_NULLS ON模式),因为数据库不知道该取分组里哪条的totalcst。
正确的解决方案:用窗口函数
最适合这类「分组取Top N」场景的是窗口函数,比如ROW_NUMBER()或RANK(),我们可以先给每个日期下的记录按totalcst降序排名,再筛选出排名第一的记录。
方案1:只取每日最大的一条(如果有相同最大值,只保留一条)
WITH daily_ranked AS ( SELECT date, pid, quan * cst AS totalcst, -- 按日期分组,每组内按totalcst降序排,给每条记录打排名 ROW_NUMBER() OVER (PARTITION BY date ORDER BY quan * cst DESC) AS rank_num FROM dbo.test1 ) SELECT date, pid, totalcst FROM daily_ranked WHERE rank_num = 1;
方案2:保留每日所有最大值记录(如果同一天有多个相同的最大totalcst,都保留)
如果你的业务允许同一天存在多个相同的最大totalcst,把ROW_NUMBER()换成RANK()即可:
WITH daily_ranked AS ( SELECT date, pid, quan * cst AS totalcst, RANK() OVER (PARTITION BY date ORDER BY quan * cst DESC) AS rank_num FROM dbo.test1 ) SELECT date, pid, totalcst FROM daily_ranked WHERE rank_num = 1;
补充说明
PARTITION BY date:把数据按日期拆分成独立的组ORDER BY quan * cst DESC:在每个日期组内,按totalcst从大到小排序ROW_NUMBER()会给每个组内的记录分配唯一的排名,即使值相同排名也不同;RANK()会给相同值分配相同的排名,后续排名会跳过(比如两个第一,下一个就是第三)
你可以根据自己的业务需求选择其中一种方案,应该就能得到你想要的结果啦~
内容的提问来源于stack exchange,提问作者Dennyc
相关产品推荐
相关产品推荐

