按日期分组并限定每组取市值Top3求和的实现方法
嘿,这个需求我之前帮不少人解决过,本质就是分组内排名后聚合求和,我给你整理了几种常用数据库的实现方案,你按需取用就行:
核心思路
先按date分组,给每个日期下的币种按market_cap降序排名,筛选出排名≤3的记录,最后再按日期对这些记录的市值求和。
各数据库具体实现
MySQL 8.0+ / PostgreSQL / SQL Server(支持窗口函数)
这类数据库支持窗口函数,实现起来最简洁,还能灵活处理并列排名的情况:
SELECT date, SUM(market_cap) AS top3_market_cap_sum FROM ( SELECT date, coin_name, market_cap, -- 按日期分组,市值降序排名,并列第三的币种会被全部纳入 RANK() OVER (PARTITION BY date ORDER BY market_cap DESC) AS cap_rank -- 如果只想严格取前3条(哪怕有并列只选3个),替换成: -- ROW_NUMBER() OVER (PARTITION BY date ORDER BY market_cap DESC) AS cap_rank -- 如果需要连续排名(比如1,2,2,3),用DENSE_RANK() FROM your_table_name ) ranked WHERE cap_rank <= 3 GROUP BY date ORDER BY date;
注意:把
your_table_name替换成你实际的表名,三种排名函数的区别可以根据你的业务需求选择。
老版本MySQL(无窗口函数,如5.x)
如果你的MySQL版本不支持窗口函数,可以用变量来模拟排名:
SELECT date, SUM(market_cap) AS top3_market_cap_sum FROM ( SELECT t.*, @rank := IF(@current_date = date, @rank + 1, 1) AS cap_rank, @current_date := date FROM ( -- 先按日期、市值降序排序,确保排名逻辑正确 SELECT date, coin_name, market_cap FROM your_table_name ORDER BY date, market_cap DESC ) t, -- 初始化变量 (SELECT @current_date := '', @rank := 0) vars ) ranked WHERE cap_rank <= 3 GROUP BY date ORDER BY date;
额外注意事项
- 确保
market_cap字段是数值类型(比如INT、DECIMAL),否则排序和求和会出错 - 如果存在
market_cap为NULL的记录,建议提前过滤(比如加WHERE market_cap IS NOT NULL),避免影响排名和求和结果
内容的提问来源于stack exchange,提问作者124697
相关产品推荐
相关产品推荐

