You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SQL实现分组内移除两组最高值?

如何用SQL按季度分组并移除每组中最高的两个MOB值?

当然可以实现!从你的示例来看,需求是按季度分组,每个季度里要删掉MOB值最高的两个等级对应的所有记录(比如2016Q1删MOB=26和25的所有行,2016Q2删MOB=19和18的所有行)。下面给你一套通用的解决方案,大部分主流数据库(MySQL 8+、PostgreSQL、SQL Server、Oracle等)都支持:

核心思路

先给每个季度内的MOB值按降序做排名,相同的MOB值分配相同的排名,然后只保留排名大于2的记录——这样就自动去掉了每个季度里最高的两个MOB组。

具体SQL代码

用CTE(公共表表达式)的写法(推荐,可读性强)

WITH ranked_mob AS (
    SELECT 
        Quarter,
        MOB,
        Amount,
        -- 按季度分组,MOB降序排名,相同MOB排名一致
        DENSE_RANK() OVER (PARTITION BY Quarter ORDER BY MOB DESC) AS mob_rank
    FROM your_table_name -- 替换成你的实际表名
)
SELECT Quarter, MOB, Amount
FROM ranked_mob
WHERE mob_rank > 2;

兼容老版本数据库的子查询写法

如果你的数据库不支持CTE(比如MySQL 5.x及以前),可以改用子查询:

SELECT Quarter, MOB, Amount
FROM (
    SELECT 
        Quarter,
        MOB,
        Amount,
        DENSE_RANK() OVER (PARTITION BY Quarter ORDER BY MOB DESC) AS mob_rank
    FROM your_table_name -- 替换成你的实际表名
) AS subquery
WHERE mob_rank > 2;

为什么用DENSE_RANK()而不是RANK()/ROW_NUMBER()?

  • DENSE_RANK()会给相同的MOB值分配相同的排名,比如2016Q2里两个MOB=19的记录都会得到mob_rank=1,两个MOB=18的记录得到mob_rank=2,这样筛选mob_rank>2就会把这两个MOB组的所有记录都排除,完全符合你的需求。
  • 如果用ROW_NUMBER(),会给每一行单独编号,那可能只会删掉每个季度的前两行,而不是整个最高的两个MOB组,这不符合你的示例要求。
  • RANK()和DENSE_RANK()的区别是,当有相同排名时,RANK()会跳过后续的排名号(比如两个1之后直接是3),但在这里用RANK()也能得到正确结果,不过DENSE_RANK()更直观。

验证示例数据

用你的测试数据跑这个SQL,结果会是:

Quarter MOB Amount
2016Q1 24 8520
2016Q1 23 15200
2016Q1 22 3000
2016Q2 17 9530
2016Q2 17 4000
2016Q2 16 8900
2016Q2 16 4550

完全符合你要移除每组最高两个MOB值记录的要求。

内容的提问来源于stack exchange,提问作者Jeremy Wik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:44:28