学习MySQL(五):窗口函数

2024年 4月 29日 55.9k 0

点击蓝字,关注我

Every Day

芙蓉楼送辛渐

[作者] 王昌龄 [朝代] 唐

寒雨连江夜入吴,平明送客楚山孤。

洛阳亲友如相问,一片冰心在玉壶。

窗口函数介绍

    窗口函数的引入是为了解决想要既显示聚集前的数据,又要显示聚集后的数据;窗口数对一组值进行操作,不需要使用GROUP BY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。

    强调:使用MySQL 8.0版本方可实现

基本语法

函数名(列) over(选项) 选项为partition by 列 order by 列

解释:

  • over(partition by xxx) 按xxx分组的所有行进行分组

  • over(partition by xxx order by aaa) 按列xxx分组,按列aaa排序

  • over(order by aaa) 按aaa列排序

  • over括号中的partition by和order by的使用根据具体情况选择

    -- 需求:计算每个学生的及格科目数
    -- 使用聚合函数,类似数据透视表,原有表结构已发生变化
    SELECT student_id,count( sid ) FROM score WHERE num >= 60 GROUP BY student_id;


    -- 使用窗口函数,不会更改原表结构
    SELECT student_id,count( sid ) over ( PARTITION BY student_id ORDER BY student_id ) AS 及格数
    FROM score WHERE num >= 60;

    聚合窗口函数

    语法:聚合函数(列) over(partition by 列 order by 列)

    常见的聚合函数:sum() count() avg() max() min()

    排序窗口函数

    • row_number():仅仅根据行号进行排序,相同结果则排序按照顺序依次排

    • rank():排名,与row_number函数不同的是,rank函数考虑到了over子句中排序字段值相同的情况,over子句中排序字段值相同的排序结果是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个。如:11335

    • dense_rank():密集排序,用法跟rank类似,唯一不同是当排序结果相同时,排序不跳跃,而是紧跟排下一个。如:11223

    • ntile():桶排序,首先,ntile会先根据你的分组依据,然后把每个组的总记录数进行按照你给的ntile(n)里的数字n进行均分,这个数字就是桶数,例如一个组内总共12条记录,若n=6,则等划分成6桶,然后按照num的排序等级划分,12/6=2则每个桶两条记录,也就是112233445566的排序结果,常用于提取前百分之多少的应用场景。

    都是排名函数,不同之处在对于名次相同的数据处理方式

      -- 对每门课程进行排序
      SELECT
      s.sid,
      s1.sname,
      s1.gender,
      c.cname,
      s.num,
      row_number() over ( PARTITION BY c.cname ORDER BY num DESC ) AS row_number排名,
      rank() over ( PARTITION BY c.cname ORDER BY num DESC ) AS rank排名,
      dense_rank() over ( PARTITION BY c.cname ORDER BY num DESC ) AS dense_rank排名,
      ntile( 6 ) over ( PARTITION BY c.cname ORDER BY num DESC ) AS ntile排名
      FROM
      score AS s
      JOIN student AS s1 ON s.student_id = s1.sid
      LEFT JOIN course AS c ON s.course_id = c.cid


      -- 计算每门课程前三,考虑排名相同的情况
      SELECT * FROM (
      SELECT
      s.sid,
      s1.sname,
      s1.gender,
      c.cname,
      s.num,
      dense_rank() over ( PARTITION BY c.cname ORDER BY num DESC ) AS dense_rank排名
      FROM
      score AS s
      JOIN student AS s1 ON s.student_id = s1.sid
      LEFT JOIN course AS c ON s.course_id = c.cid
      ) AS a
      WHERE
      dense_rank排名

      相关文章

      Oracle如何使用授予和撤销权限的语法和示例
      Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
      下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
      社区版oceanbase安装
      Oracle 导出CSV工具-sqluldr2
      ETL数据集成丨快速将MySQL数据迁移至Doris数据库

      发布评论