• 分组排序后取指定顺序数据 - 开窗/分析 函数


              和聚合函数对应着看,聚合函数是通过指定一列来统计单行数据的。开窗函数是多行。

    建表(Oracle):

    1. create table t_score(
    2. stuId varchar2(20),
    3. stuName varchar2(50),
    4. classId number,
    5. score float
    6. );
    7. insert into t_score(stuId,stuName,classId,score) values('111','小王',1,92);
    8. insert into t_score(stuId,stuName,classId,score) values('123','小李',1,90);
    9. insert into t_score(stuId,stuName,classId,score) values('134','小钱',1,92);
    10. insert into t_score(stuId,stuName,classId,score) values('145','小顺',1,100);
    11. insert into t_score(stuId,stuName,classId,score) values('121','小A',2,92);
    12. insert into t_score(stuId,stuName,classId,score) values('131','小B',2,90);
    13. insert into t_score(stuId,stuName,classId,score) values('141','小C',3,92);
    14. insert into t_score(stuId,stuName,classId,score) values('151','小D',3,100);

    分析函数:

     

     场景: 查询每个班的第一名

            步骤一:每个班的学生在自己的班级里排序

    1. select
    2. -- 表的原始字段
    3. stuId,
    4. stuName,
    5. classId,
    6. score,
    7. -- 多查一个排序字段
    8. row_number() over(partition by classId order by score desc) rn
    9. from t_score

             

            步骤二:找到想要的排名,以第一名为例

    1. -- row_number() 不存在并列,一定是1.2.3....N
    2. select *
    3. from (select
    4. -- 表的原始字段
    5. stuId,
    6. stuName,
    7. classId,
    8. score,
    9. -- 多查一个排序字段
    10. -- row_number是一个内置函数,用来生成序号, over加在聚合函数后面表示row_number当作窗口函数(多行),而不是聚合函数(一行),partition by表示用指定字段进行分区,即依据字段值的不同来做分区表(以classid分区,则可以看作每个班级都是一个独立的分区表),因此后面的order by也是在分区表中生效,不会在全表里排序
    11. row_number() over(partition by classId order by score desc) rn
    12. from t_score)
    13. where rn = 1; -- rn 就是序号, rn=1表示排序后的第一个,rn=2表示第二个,以此类推

            分析:首先通过窗口函数把每个班的学生按班级为单位做了分区,然后用分数做降序排列。这样就得到了一个有序号的,以班级为单位的分区表。最后只要找排名(rn=?)即可。

    补充:rank()函数,统计并列情况

    1. -- rank 存在并列的情况, 1.2.2.4....N
    2. -- dense_rank 1.2.2.3.4...N
    3. select stuId,
    4. stuName,
    5. classId,
    6. score,
    7. -- 聚合函数rank后面加上over() 表示这是一个开窗函数,即查出来是多行(group by出来是一行),每行都有一个开窗函数的结果,partition by是指以哪个字段做分区,classid做分区,则表示1.2.3 三个班都是独立的分区表,后面的order by也是在独立分区表里面排序
    8. rank() over(partition by classId order by score desc) rn
    9. from t_score;

     使用rank函数会把数据相同的几项的序号认为是一样的,后面的排序会跳过并列的数量。

  • 相关阅读:
    Zookeeper-3.8.0单台、集群环境搭建
    负载均衡的原理及其算法详解
    Monitoring techniques in AWS
    C++的四种强制类型转换
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java学生出国境学习交流管理87153
    One way 和two way ANOVA分析的区别是啥,以及如何使用SPSS或者prism进行统计分析
    SQLAlchemy 连接池
    22-Docker-常用命令详解-docker pull
    c#构建具有用户认证与管理的socks5代理服务端
    Promise异步编程
  • 原文地址:https://blog.csdn.net/nickDaDa/article/details/126361239