MySQL窗口函数OVER()

本文详细介绍了MySQL的窗口函数OVER(),包括其与PARTITION BY和ORDER BY子句的结合使用,以及如何与SUM()等聚合函数配合,提供实例展示了在数据库查询中的应用。同时还提到了ORDER BY在窗口函数中的作用,以及与FORMAT、CAST和CONVERT函数在格式化输出和排序上的差异。文章末尾还提及了窗口函数与其他排序函数如ROW_NUMBER()、DENSE_RANK()和RANK()的结合使用。
摘要由CSDN通过智能技术生成

下面的讲解将基于这个employee2表:

mysql> SELECT * FROM employee2;
+----+-----------+------+---------+---------+
| id | name      | age  | salary  | dept_id |
+----+-----------+------+---------+---------+
|  3 | 小肖      |   29 | 30000.0 |       1 |
|  4 | 小东      |   30 | 40000.0 |       2 |
|  6 | 小非      |   24 | 23456.0 |       3 |
|  7 | 晓飞      |   30 | 15000.0 |       4 |
|  8 | 小林      |   23 | 24000.0 |    NULL |
| 10 | 小五      |   20 |  4500.0 |    NULL |
| 11 | 张山      |   24 | 40000.0 |       1 |
| 12 | 小肖      |   28 | 35000.0 |       2 |
| 13 | 李四      |   23 | 50000.0 |       1 |
| 17 | 王武      |   24 | 56000.0 |       2 |
| 18 | 猪小屁    |    2 | 56000.0 |       2 |
| 19 | 小玉      |   25 | 58000.0 |       1 |
| 21 | 小张      |   23 | 50000.0 |       1 |
| 22 | 小胡      |   25 | 25000.0 |       2 |
| 96 | 小肖      |   19 | 35000.0 |       1 |
| 97 | 小林      |   20 | 20000.0 |       2 |
+----+-----------+------+---------+---------+
16 rows in set (0.00 sec)

窗口函数是OVER(),其中对应子句有PARTITION BY 以及 ORDER BY子句,所以形式有:

  • OVER():这时候,是一个空子句,此时的效果和没有使用OVER()函数是一样的,作用的是这个表所有数据构成的窗口

    mysql> SELECT
        -> name,
        -> salary,
        -> MAX(salary) OVER() AS max_salary -- 作用于一整个窗口,此时返回的是所有数据中的MAX(salary),表示所有员工的最大工资
        -> FROM employee2;
    +-----------+---------+------------+
    | name      | salary  | max_salary |
    +-----------+---------+------------+
    | 小肖      | 30000.0 |    58000.0 |
    | 小东      | 40000.0 |    58000.0 |
    | 小非      | 23456.0 |    58000.0 |
    | 晓飞      | 15000.0 |    58000.0 |
    | 小林      | 24000.0 |    58000.0 |
    | 小五      |  4500.0 |    58000.0 |
    | 张山      | 40000.0 |    58000.0 |
    | 小肖      | 35000.0 |    58000.0 |
    | 李四      | 50000.0 |    58000.0 |
    | 王武      | 56000.0 |    58000.0 |
    | 猪小屁    | 56000.0 |    58000.0 |
    | 小玉      | 58000.0 |    58000.0 |
    | 小张      | 50000.0 |    58000.0 |
    | 小胡      | 25000.0 |    58000.0 |
    | 小肖      | 35000.0 |    58000.0 |
    | 小林      | 20000.0 |    58000.0 |
    +-----------+---------+------------+
    16 rows in set (0.00 sec)
    
    mysql> SELECT
        -> name,
        -> salary,
        -> MAX(salary) OVER() -- 获取部门为1的所有员工的name,salary以及这个部门的最大工资
        -> FROM employee2
        -> WHERE dept_id = 1;
    +--------+---------+--------------------+
    | name   | salary  | MAX(salary) OVER() |
    +--------+---------+--------------------+
    | 小肖   | 30000.0 |            58000.0 |
    | 张山   | 40000.0 |            58000.0 |
    | 李四   | 50000.0 |            58000.0 |
    | 小玉   | 58000.0 |            58000.0 |
    | 小张   | 50000.0 |            58000.0 |
    | 小肖   | 35000.0 |            58000.0 |
    +--------+---------+--------------------+
    6 rows in set (0.00 sec)
    
  • OVER(PARTITION BY yyy1,yyy2,yyy3):含有了PARTITION BY 子句,此时就会根据yyy1,yyy2,yyy3这些列构成的整体进行划分窗口,只有这些列构成的整体相同,才会处在同一个窗口中

    mysql> SELECT
        -> name,
        -> salary,
        -> MAX(salary) OVER(PARTITION BY dept_id) AS dept_max_salary -- 利用了PARTITION BY ,从而根据dept_id进行分组,然后获取每个分组的最大值
        -> FROM employee2;
    +-----------+---------+-----------------+
    | name      | salary  | dept_max_salary |
    +-----------+---------+-----------------+
    | 小林      | 24000.0 |         24000.0 | --|   分组为NULL的
    | 小五      |  4500.0 |         24000.0 | --|
    | 小肖      | 30000.0 |         58000.0 | -----|
    | 张山      | 40000.0 |         58000.0 |
    | 李四      | 50000.0 |         58000.0 |     -- 分组为dept_id = 1的
    | 小玉      | 58000.0 |         58000.0 |
    | 小张      | 50000.0 |         58000.0 |
    | 小肖      | 35000.0 |         58000.0 | -----|
    | 小东      | 40000.0 |         56000.0 | ---------|
    | 小肖      | 35000.0 |         56000.0 |
    | 王武      | 56000.0 |         56000.0 |
    | 猪小屁    | 56000.0 |         56000.0 |      -- 分组为dept_id = 2的
    | 小胡      | 25000.0 |         56000.0 |
    | 小林      | 20000.0 |         56000.0 | ---------|
    | 小非      | 23456.0 |         23456.0 | -- ------------| 分组为dept_id = 3的
    | 晓飞      | 15000.0 |         15000.0 | -- --------------| 分组为dept_id = 4的
    +-----------+---------+-----------------+
    16 rows in set (0.00 sec)
    
  • OVER(ORDER BY yyy1,yyy2,yyy3 ASCDESC):每个窗口中利用ORDER BY子句,这时候将按照yyy1进行对应的升序降序的顺序进行排序,如果yyy1相同,将根据yyy2排序(和ORDER BY 的用法一样),这时候不仅会进行排序操作,如果是SUM与其连用的话,同时进行了累加的操作,即值是当前行加上前一行对应的值。但是下面的例子中却发现ORDER BY 后面对应的值相同的时候,并不是当前这一行加上以前行的值,例如ORDER BY salaryORDER BY name的时候

    mysql> SELECT
        -> name,
        -> salary,
        -> SUM(salary) OVER(ORDER BY salary) AS already_paid_salary -- 利用ORDER BY ,窗口中对应的行将按照salary进行升序排序,然后调用SUM聚集 函数,不同的窗口进行累计
        -> FROM employee2;
    +-----------+---------+---------------------+
    | name      | salary  | already_paid_salary |
    +-----------+---------+---------------------+
    | 小五      |  4500.0 |              4500.0 |
    | 晓飞      | 15000.0 |             19500.0 |   
    | 小林      | 20000.0 |             39500.0 |
    | 小非      | 23456.0 |             62956.0 |
    | 小林      | 24000.0 |             86956.0 |
    | 小胡      | 25000.0 |            111956.0 |
    | 小肖      | 30000.0 |            141956.0 |
    | 小肖      | 35000.0 |            211956.0 |  -- -----| 这两行同处相同,此时这个窗口的already_paid_salary
    | 小肖      | 35000.0 |            211956.0 |  -- -----| = (35000 * 2) (当前两行) + 141956(前面的行)
    | 小东      | 40000.0 |            291956.0 |  -- ---| 这两行同处相同,此时这个窗口的already_paid_salary 
    | 张山      | 40000.0 |            291956.0 |  -- ---|  = (40000 * 2)(当前两行) + 211956(之前行的)
    | 李四      | 50000.0 |            391956.0 |  -- | 道理同上
    | 小张      | 50000.0 |            391956.0 |  -- |
    | 王武      | 56000.0 |            503956.0 |  -- ------|道理同上
    | 猪小屁    | 56000.0 |            503956.0 |   -- ------|
    | 小玉      | 58000.0 |            561956.0 |
    +-----------+---------+---------------------+
    16 rows in set (0.00 sec)
    
    mysql> SELECT
        -> name,
        -> salary,
        -> SUM(salary) OVER(ORDER BY name)  -- 每个窗口的所有行将根据name进行升序排序这时候,然后不同name的行将会进行累计操作,直接是当前行+以嵌行的,相同的时候,是相同行的和加上之前行的值
        -> FROM employee2;
    +-----------+---------+---------------------------------+
    | name      | salary  | SUM(salary) OVER(ORDER BY name) |
    +-----------+---------+---------------------------------+
    | 小东      | 40000.0 |                         40000.0 |
    | 小五      |  4500.0 |                         44500.0 |
    | 小张      | 50000.0 |                         94500.0 |
    | 小林      | 24000.0 |                        138500.0 | -- |这两组同处相同,所以对应的值为(24000  + 20000)(相同的两行) + 94500(之前的行)
    | 小林      | 20000.0 |                        138500.0 | -- | 
    | 小玉      | 58000.0 |                        196500.0 |
    | 小肖  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值