DENSE_RANK() 函数的使用

业务场景:按月对每个工地状态进行评分, 满分一百分, 对每个工地评分后, 进行排名, 要求相同分数的工地排名相同

在我不知道DENSE_RANK()这个函数前, 我是对每个工地进行算分,所有工地是一个list , 工地的分数在list的map里。
如:[ { key:“工地1” , score:80 } , { key:“工地2”, score:90} , { key:“工地3”, score:60}]
在这样一个数组中, 对工地按评分排名, 其实就是把List数组按map中的某个属性进行排名。 但是这样有个问题, 就是说,相同分数的工地, 排名依然会有个先后顺序。
使用 DENSE_RANK() 可以在sql步骤就对数据进行排序, 不需要用代码进行排序。

select DZShare.T_Y_SCORE.total_score ,DZShare.T_Y_SCORE.time ,
ISNULL(DZShare.T_Y_SCORE.actual_score , 100) as actual_score  , DZShare.T_Y_SBBHDEVICE_SITE.work_site_name , 
DZShare.T_Y_SBBHDEVICE_SITE.country , DZShare.T_Y_SBBHDEVICE_SITE.id as sbbhSiteId , 
-- 这里使用DENSE_RANK() 
DENSE_RANK() over (order by actual_score desc ) rank from DZShare.T_Y_SBBHDEVICE_SITE left join DZShare.T_Y_SCORE
on  DZShare.T_Y_SBBHDEVICE_SITE.id = DZShare.T_Y_SCORE.sbbhdevice_id
and DZShare.T_Y_SCORE.time = '2021-11-01 00:00:00'
where 1=1
and DZShare.T_Y_SBBHDEVICE_SITE.country in ('临邑县' , '武城县')
and DZShare.T_Y_SBBHDEVICE_SITE.engineering_id in (1,2,3)
order by actual_score desc

使用方式:

select *  ,  DENSE_RANK() over (order by actual_score desc ) rank
from table
order by actual_score desc

over 中的写法和order by 子句保持一致。
排序效果如下:
在这里插入图片描述
可以看到, 当分数相同是, 排名rank也相同。
除了DENSE_RANK() , 相似的还有 RANK() 函数, 但 RANK() 是跳跃是排名。
什么是跳跃是排名? 我们把sql中的DENSE_RANK() 替换成 RANK() , 会得到如下结果:
在这里插入图片描述
当分值都是100 分的工地排名完成后,(都是第一名),然后从当前不是100分的工地位置开始排名计数。也就是分数是75的工地从46位置开始, 那么就从第46开始接着排名。

以上是使用sql进行排名, 那么使用代码进行排名,就是对List中的Map的某个属性进行排名, 当属性相同时,如何确保排名也相同呢?
1:首先定义一个排序方法,对list进行排序, 让list有序

    //降序排序
    class MapComparatorDesc implements Comparator<Map<String, Object>> {
        @Override
        public int compare(Map<String, Object> m1, Map<String, Object> m2) {
            Double v1 = Double.valueOf(m1.get("countryNumber").toString());
            Double v2 = Double.valueOf(m2.get("countryNumber").toString());
            if (v2 != null) {
                return v2.compareTo(v1);
            }
            return 0;
        }

    }
    // 对lsit进行排序
Collections.sort(tyScoreCountryList, new MapComparatorDesc());

然后对有序后的list , 按照map中的属性值, 给每个元素一个排名,具体如下:

        // 增加排名字段
        Map rankMap = new HashMap();
        Integer rank =0;
        for(int u=0; u<tyScoreCountryList.size(); u++)
        {
            String countryNumber = tyScoreCountryList.get(u).get("countryNumber").toString();
            if(rankMap.containsKey(countryNumber))
            {
                tyScoreCountryList.get(u).put("rank" , rank);
            }
            else {
                rank+=1;
                tyScoreCountryList.get(u).put("rank" ,rank);
                rankMap.put(countryNumber , null);
            }
        }

这里 countryNumber就是工地分数,在保证list是有序的前提下, 按判断分数在rankMap中存不存在来对List添加排名字段,可以实现对list的排名。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值