MySQL高级窗口函数简介

备注:测试数据库版本为MySQL 8.0

这个blog我们来聊聊MySQL高级窗口函数
窗口函数在复杂查询以及数据仓库中应用得比较频繁
与sql打交道比较多的技术人员都需要掌握

如需要scott用户下建表及录入数据语句,可参考:
scott建表及录入数据sql脚本

函数名 函数用途
row_number 对行进行排序并为每一行增加一个唯一编号。这是一个非确定性函数
rank 将数据行值按照排序后的顺序进行排名,在有并列的情况下排名值将被跳过
dense_rank 将数据行值按照排序后的顺序进行排名,在有并列的情况下也不跳过排名值
lag 访问一个分区或结果集中之前的一行
lead 访问一个分区或结果集中之后的一行
first_value 访问一个分区或结果集中第一行
last_value 访问一个分区或结果集中最后一行
nth_value 访问一个分区或结果集中的任意一行
percent_rank 将计算得到的排名值标准化
CUME_DIST() 将计算得到的排名值标准化
NTILE 将数据进行将数据行分组为单元

分析函数有3个基本组成部分:
1.分区子句
2.排序子句
3.开窗子句

function1 (argument1,argument2,..argumentN)
over  w
window w as ([partition-by-clause] [order-by-clause] [windowing-clause])

窗口说明子句的语法:
默认的窗口子句是rows between unbounded preceding and current row。如果你没有显示声明窗口,就将会使用默认窗口。
并不是所有的分析函数都支持开窗子句

[rows | range] between <start expr> and [end expr]

whereas
<start expr> is [unbounded preceding | current row | n preceding | n following]
<end expr> is [unbounded following | current row | n preceding | n following]

一.row_number、rank、dense_rank

row_number语法:

row_number() over w
window w as (partition-clause order-by-clause)

row_number不支持开窗子句
rank、dense_rank语法同row_number语法

现在需要对分不同部门来看部门内的工资排名,且从大到小排列:

-- 可以看到deptno为30的员工工资有重复的,重复的工资为1250
-- row_number()  不关注重复的,直接排名,1-2-3-4-5-6
-- rank()        重复排名,会跳过,1-2-3-4-4-6
-- dense_rank()  重复排名,不跳过,1-2-3-4-4-5
select a.empno,
       a.ename,
       a.deptno,
       a.sal,
       row_number() over w as 'num',
       rank() over w as 'rank',
       dense_rank() over w  as 'dense_rank'
  from emp a
  window w as (partition by a.deptno order by a.sal desc)
;
mysql> select a.empno,
    ->        a.ename,
    ->        a.deptno,
    ->        a.sal,
    ->        row_number() over w as 'num',
    ->        rank() over w as 'rank',
    ->        dense_rank() over w  as 'dense_rank'
    ->   from emp a
    ->   window w as (partition by a.deptno order by a.sal desc)
    -> ;
+-------+--------+--------+---------+-----+------+------------+
| empno | ename  | deptno | sal     | num | rank | dense_rank |
+-------+--------+--------+---------+-----+------+------------+
|  7839 | KING   |     10 | 5000.00 |   1 |    1 |          1 |
|  7782 | CLARK  |     10 | 2450.00 |   2 |    2 |          2 |
|  7934 | MILLER |     10 | 1300.00 |   3 |    3 |          3 |
|  7788 | SCOTT  |     20 | 3000.00 |   1 |    1 |          1 |
|  7902 | FORD   |     20 | 3000.00 |   2 |    1 |          1 |
|  7566 | JONES  |     20 | 2975.00 |   3 |    3 |          2 |
|  7876 | ADAMS  |     20 | 1100.00 |   4 |    4 |          3 |
|  7369 | SMITH  |     20 |  800.00 |   5 |    5 |          4 |
|  7698 | BLAKE  |     30 | 2850.00 |   1 |    1 |          1 |
|  7499 | ALLEN  |     30 | 1600.00 |   2 |    2 |          2 |
|  7844 | TURNER |     30 | 1500.00 |   3 |    3 |          3 |
|  7521 | WARD   |     30 | 1250.00 |   4 |    4 |          4 |
|  7654 | MARTIN |     30 | 1250.00 |   5 |    4 |          4 |
|  7900 | JAMES  |     30 |  950.00 |   6 |    6 |          5 |
+-------+--------+--------+---------+-----+------+------------+
14 rows in set (0.01 sec)

二.lag、lead

lag语法:

lag (expression, offset, default) over w
window w as  (partition-clause order-by-clause)

lag不支持开窗子句
lead同lag语法

-- 根据分组,取值上n条和下n条   如果是第一条或最后一条,就给个默认值
SELECT a.empno,
       a.deptno,
       a.hiredate,
       a.sal,
       lag(sal, 1, 0) over w as 'pre_sal',
       lead(sal, 1, 0) over w as 'next_sal',
       lag(sal, 2, 0) over w  as 'pre2_sal',
       lead(sal, 2, 0) over w as 'next_2sal'
  FROM emp a
  window w  as (PARTITION BY a.deptno ORDER BY hiredate ASC)
;
mysql> SELECT a.empno,
    ->        a.deptno,
    ->        a.hiredate,
    ->        a.sal,
    ->        lag(sal, 1, 0) over w as 'pre_sal',
    ->        lead(sal, 1, 0) over w as 'next_sal',
    ->        lag(sal, 2, 0) over w  as 'pre2_sal',
    ->        lead(sal, 2, 0) over w as 'next_2sal'
    ->   FROM emp a
    ->   window w  as (PARTITION BY a.deptno ORDER BY hiredate ASC)
    -> ;
+-------+--------+------------+---------+---------+----------+----------+-----------+
| empno | deptno | hiredate   | sal     | pre_sal | next_sal | pre2_sal | next_2sal |
+-------+--------+------------+---------+---------+----------+----------+-----------+
|  7782 |     10 | 1981-06-09 | 2450.00 |    0.00 |  5000.00 |     0.00 |   1300.00 |
|  7839 |     10 | 1981-11-17 | 5000.00 | 2450.00 |  1300.00 |     0.00 |      0.00 |
|  7934 |     10 | 1982-01-23 | 1300.00 | 5000.00 |     0.00 |  2450.00 |      0.00 |
|  7369 |     20 | 1980-12-17 |  800.00 |    0.00 |  2975.00 |     0.00 |   3000.00 |
|  7566 |     20 | 1981-04-02 | 2975.00 |  800.00 |  3000.00 |     0.00 |   3000.00 |
|  7902 |     20 | 1981-12-03 | 3000.00 | 2975.00 |  3000.00 |   800.00 |   1100.00 |
|  7788 |     20 | 1987-06-13 | 3000.00 | 3000.00 |  1100.00 |  2975.00 |      0.00 |
|  7876 |     20 | 1987-06-13 | 1100.00 | 3000.00 |     0.00 |  3000.00 |      0.00 |
|  7499 |     30 | 1981-02-20 | 1600.00 |    0.00 |  1250.00 |     0.00 |   2850.00 |
|  7521 |     30 | 1981-02-22 | 1250.00 | 1600.00 |  2850.00 |     0.00 |   1500.00 |
|  7698 |     30 | 1981-05-01 | 2850.00 | 1250.00 |  1500.00 |  1600.00 |   1250.00 |
|  7844 |     30 | 1981-09-08 | 1500.00 | 2850.00 |  1250.00 |  1250.00 |    950.00 |
|  7654 |     30 | 1981-09-28 | 1250.00 | 1500.00 |   950.00 |  2850.00 |      0.00 |
|  7900 |     30 | 1981-12-03 |  950.00 | 1250.00 |     0.00 |  1500.00 |      0.00 |
+-------+--------+------------+---------+---------+----------+----------+-----------+
14 rows in set (0.00 sec)

-- 没有比自己小我的我们设为AAA,没有比自己大的,我们设置为ZZZ
select deptno,
       ename,
       lag(ename, 1, 'AAA') over w as 'lower_name',
       lead(ename, 1, 'ZZZ') over w as 'higher_name'
  from emp
window w as(PARTITION BY deptno ORDER BY ename)
;

-- 部门重复的话值输出第一行的部门编号  
select (case when deptno= lag(deptno,1)over w then null else deptno end) as 'deptno',
        ename,
       lag(ename, 1, 'AAA') over w  as 'lower_name',
       lead(ename, 1, 'ZZZ') over w as 'higher_name'
  from emp
window w  as (PARTITION BY deptno ORDER BY ename)
;
mysql> -- 没有比自己小我的我们设为AAA,没有比自己大的,我们设置为ZZZ
mysql> select deptno,
    ->        ename,
    ->        lag(ename, 1, 'AAA') over w as 'lower_name',
    ->        lead(ename, 1, 'ZZZ') over w as 'higher_name'
    ->   from emp
    -> window w as(PARTITION BY deptno ORDER BY ename)
    -> ;
+--------+--------+------------+-------------+
| deptno | ename  | lower_name | higher_name |
+--------+--------+------------+-------------+
|     10 | CLARK  | AAA        | KING        |
|     10 | KING   | CLARK      | MILLER      |
|     10 | MILLER | KING       | ZZZ         |
|     20 | ADAMS  | AAA        | FORD        |
|     20 | FORD   | ADAMS      | JONES       |
|     20 | JONES  | FORD       | SCOTT       |
|     20 | SCOTT  | JONES      | SMITH       |
|     20 | SMITH  | SCOTT      | ZZZ         |
|     30 | ALLEN  | AAA        | BLAKE       |
|     30 | BLAKE  | ALLEN      | JAMES       |
|     30 | JAMES  | BLAKE      | MARTIN      |
|     30 | MARTIN | JAMES      | TURNER      |
|     30 | TURNER | MARTIN     | WARD        |
|     30 | WARD   | TURNER     | ZZZ         |
+--------+--------+------------+-------------+
14 rows in set (0.00 sec)

mysql>
mysql> -- 部门重复的话值输出第一行的部门编号
mysql> select (case when deptno= lag(deptno,1)over w then null else deptno end) as 'deptno',
    ->         ename,
    ->        lag(ename, 1, 'AAA') over w  as 'lower_name',
    ->        lead(ename, 1, 'ZZZ') over w as 'higher_name'
    ->   from emp
    -> window w  as (PARTITION BY deptno ORDER BY ename)
    -> ;
+--------+--------+------------+-------------+
| deptno | ename  | lower_name | higher_name |
+--------+--------+------------+-------------+
|     10 | CLARK  | AAA        | KING        |
|   NULL | KING   | CLARK      | MILLER      |
|   NULL | MILLER | KING       | ZZZ         |
|     20 | ADAMS  | AAA        | FORD        |
|   NULL | FORD   | ADAMS      | JONES       |
|   NULL | JONES  | FORD       | SCOTT       |
|   NULL | SCOTT  | JONES      | SMITH       |
|   NULL | SMITH  | SCOTT      | ZZZ         |
|     30 | ALLEN  | AAA        | BLAKE       |
|   NULL | BLAKE  | ALLEN      | JAMES       |
|   NULL | JAMES  | BLAKE      | MARTIN      |
|   NULL | MARTIN | JAMES      | TURNER      |
|   NULL | TURNER | MARTIN     | WARD        |
|   NULL | WARD   | TURNER     | ZZZ         |
+--------+--------+------------+-------------+
14 rows in set (0.00 sec)

三.first_value、last_value、nth_value

first_value、last_value语法:

first_value(expression) over w 
window w as  (partition-clause order-by-clause windowing-clause)
last_value(expression) over w
window w as  (partition-clause order-by-clause windowing-clause)

nth_value语法:

nth_value (measure, n) [ from first | from last ] [ respect nulls | ignore nulls ]
over  w
window w as  (partitioning-clause order-by-clause windowing-clause) 
/*
需求:求每个部门工资最高的和工资最低的以及工资第二高的
*/

-- 默认不带开窗子句,从第一行到当前行
select a.empno,a.deptno,a.sal,
       first_value(a.sal)  over w as 'first',
       last_value(a.sal) over w as 'last',
       nth_value(a.sal,2) over w as 'top_2'
  from emp a
  window w  as (partition by a.deptno order by sal)
;

-- rows between unbounded preceding and current row  从第一行到当前行
select a.empno,a.deptno,a.sal,
       first_value(a.sal)  over w as 'first',
       last_value(a.sal) over w as 'last',
       nth_value(a.sal,2) over w as 'top_2'
  from emp a
   window w  as (partition by a.deptno order by sal rows between unbounded preceding and current row)
;
  

-- rows between unbounded preceding and unbounded following 从第一行到最后一行
 select a.empno,a.deptno,a.sal,
       first_value(a.sal)  over w as 'first',
       last_value(a.sal) over w as 'last',
       nth_value(a.sal,2) over w as 'top_2'
  from emp a
 window w  as (partition by a.deptno order by sal rows between unbounded preceding and unbounded following)
; 
 
 -- 1 preceding and 1 following   当前行的前一行到当前行的后一行 
  select a.empno,a.deptno,a.sal,
       first_value(a.sal)  over w as 'first',
       last_value(a.sal) over w as 'last',
       nth_value(a.sal,2) over w as 'top_2'
  from emp a
 window w  as (partition by a.deptno order by sal rows between 1 preceding and 1 following)
; 
mysql> -- 默认不带开窗子句,从第一行到当前行
mysql> select a.empno,a.deptno,a.sal,
    ->        first_value(a.sal)  over w as 'first',
    ->        last_value(a.sal) over w as 'last',
    ->        nth_value(a.sal,2) over w as 'top_2'
    ->   from emp a
    ->   window w  as (partition by a.deptno order by sal)
    -> ;
+-------+--------+---------+---------+---------+---------+
| empno | deptno | sal     | first   | last    | top_2   |
+-------+--------+---------+---------+---------+---------+
|  7934 |     10 | 1300.00 | 1300.00 | 1300.00 |    NULL |
|  7782 |     10 | 2450.00 | 1300.00 | 2450.00 | 2450.00 |
|  7839 |     10 | 5000.00 | 1300.00 | 5000.00 | 2450.00 |
|  7369 |     20 |  800.00 |  800.00 |  800.00 |    NULL |
|  7876 |     20 | 1100.00 |  800.00 | 1100.00 | 1100.00 |
|  7566 |     20 | 2975.00 |  800.00 | 2975.00 | 1100.00 |
|  7788 |     20 | 3000.00 |  800.00 | 3000.00 | 1100.00 |
|  7902 |     20 | 3000.00 |  800.00 | 3000.00 | 1100.00 |
|  7900 |     30 |  950.00 |  950.00 |  950.00 |    NULL |
|  7521 |     30 | 1250.00 |  950.00 | 1250.00 | 1250.00 |
|  7654 |     30 | 1250.00 |  950.00 | 1250.00 | 1250.00 |
|  7844 |     30 | 1500.00 |  950.00 | 1500.00 | 1250.00 |
|  7499 |     30 | 1600.00 |  950.00 | 1600.00 | 1250.00 |
|  7698 |     30 | 2850.00 |  950.00 | 2850.00 | 1250.00 |
+-------+--------+---------+---------+---------+---------+
14 rows in set (0.00 sec)

mysql>
mysql> -- rows between unbounded preceding and current row  从第一行到当前行
mysql> select a.empno,a.deptno,a.sal,
    ->        first_value(a.sal)  over w as 'first',
    ->        last_value(a.sal) over w as 'last',
    ->        nth_value(a.sal,2) over w as 'top_2'
    ->   from emp a
    ->    window w  as (partition by a.deptno order by sal rows between unbounded preceding and current row)
    -> ;
+-------+--------+---------+---------+---------+---------+
| empno | deptno | sal     | first   | last    | top_2   |
+-------+--------+---------+---------+---------+---------+
|  7934 |     10 | 1300.00 | 1300.00 | 1300.00 |    NULL |
|  7782 |     10 | 2450.00 | 1300.00 | 2450.00 | 2450.00 |
|  7839 |     10 | 5000.00 | 1300.00 | 5000.00 | 2450.00 |
|  7369 |     20 |  800.00 |  800.00 |  800.00 |    NULL |
|  7876 |     20 | 1100.00 |  800.00 | 1100.00 | 1100.00 |
|  7566 |     20 | 2975.00 |  800.00 | 2975.00 | 1100.00 |
|  7788 |     20 | 3000.00 |  800.00 | 3000.00 | 1100.00 |
|  7902 |     20 | 3000.00 |  800.00 | 3000.00 | 1100.00 |
|  7900 |     30 |  950.00 |  950.00 |  950.00 |    NULL |
|  7521 |     30 | 1250.00 |  950.00 | 1250.00 | 1250.00 |
|  7654 |     30 | 1250.00 |  950.00 | 1250.00 | 1250.00 |
|  7844 |     30 | 1500.00 |  950.00 | 1500.00 | 1250.00 |
|  7499 |     30 | 1600.00 |  950.00 | 1600.00 | 1250.00 |
|  7698 |     30 | 2850.00 |  950.00 | 2850.00 | 1250.00 |
+-------+--------+---------+---------+---------+---------+
14 rows in set (0.00 sec)

mysql>
mysql>
mysql> -- rows between unbounded preceding and unbounded following 从第一行到最后一行
mysql>  select a.empno,a.deptno,a.sal,
    ->        first_value(a.sal)  over w as 'first',
    ->        last_value(a.sal) over w as 'last',
    ->        nth_value(a.sal,2) over w as 'top_2'
    ->   from emp a
    ->  window w  as (partition by a.deptno order by sal rows between unbounded preceding and unbounded following)
    -> ;
+-------+--------+---------+---------+---------+---------+
| empno | deptno | sal     | first   | last    | top_2   |
+-------+--------+---------+---------+---------+---------+
|  7934 |     10 | 1300.00 | 1300.00 | 5000.00 | 2450.00 |
|  7782 |     10 | 2450.00 | 1300.00 | 5000.00 | 2450.00 |
|  7839 |     10 | 5000.00 | 1300.00 | 5000.00 | 2450.00 |
|  7369 |     20 |  800.00 |  800.00 | 3000.00 | 1100.00 |
|  7876 |     20 | 1100.00 |  800.00 | 3000.00 | 1100.00 |
|  7566 |     20 | 2975.00 |  800.00 | 3000.00 | 1100.00 |
|  7788 |     20 | 3000.00 |  800.00 | 3000.00 | 1100.00 |
|  7902 |     20 | 3000.00 |  800.00 | 3000.00 | 1100.00 |
|  7900 |     30 |  950.00 |  950.00 | 2850.00 | 1250.00 |
|  7521 |     30 | 1250.00 |  950.00 | 2850.00 | 1250.00 |
|  7654 |     30 | 1250.00 |  950.00 | 2850.00 | 1250.00 |
|  7844 |     30 | 1500.00 |  950.00 | 2850.00 | 1250.00 |
|  7499 |     30 | 1600.00 |  950.00 | 2850.00 | 1250.00 |
|  7698 |     30 | 2850.00 |  950.00 | 2850.00 | 1250.00 |
+-------+--------+---------+---------+---------+---------+
14 rows in set (0.00 sec)

mysql>
mysql>  -- 1 preceding and 1 following   当前行的前一行到当前行的后一行
mysql>   select a.empno,a.deptno,a.sal,
    ->        first_value(a.sal)  over w as 'first',
    ->        last_value(a.sal) over w as 'last',
    ->        nth_value(a.sal,2) over w as 'top_2'
    ->   from emp a
    ->  window w  as (partition by a.deptno order by sal rows between 1 preceding and 1 following)
    -> ;
+-------+--------+---------+---------+---------+---------+
| empno | deptno | sal     | first   | last    | top_2   |
+-------+--------+---------+---------+---------+---------+
|  7934 |     10 | 1300.00 | 1300.00 | 2450.00 | 2450.00 |
|  7782 |     10 | 2450.00 | 1300.00 | 5000.00 | 2450.00 |
|  7839 |     10 | 5000.00 | 2450.00 | 5000.00 | 5000.00 |
|  7369 |     20 |  800.00 |  800.00 | 1100.00 | 1100.00 |
|  7876 |     20 | 1100.00 |  800.00 | 2975.00 | 1100.00 |
|  7566 |     20 | 2975.00 | 1100.00 | 3000.00 | 2975.00 |
|  7788 |     20 | 3000.00 | 2975.00 | 3000.00 | 3000.00 |
|  7902 |     20 | 3000.00 | 3000.00 | 3000.00 | 3000.00 |
|  7900 |     30 |  950.00 |  950.00 | 1250.00 | 1250.00 |
|  7521 |     30 | 1250.00 |  950.00 | 1250.00 | 1250.00 |
|  7654 |     30 | 1250.00 | 1250.00 | 1500.00 | 1250.00 |
|  7844 |     30 | 1500.00 | 1250.00 | 1600.00 | 1500.00 |
|  7499 |     30 | 1600.00 | 1500.00 | 2850.00 | 1600.00 |
|  7698 |     30 | 2850.00 | 1600.00 | 2850.00 | 2850.00 |
+-------+--------+---------+---------+---------+---------+
14 rows in set (0.00 sec)

四.percent_rank、CUME_DIST

percent_rank语法:

percent_rank() over w
window w as  ([partition-by-clause] [order-by-clause] )

CUME_DIST语法

cume_dist() over w
window w as  ([partition-by-clause] [order-by-clause] )

percent_rank:
-- percent_rank函数以0到1之间的分数形式返回某个值在数据分区中的排名
-- percent_rank的计算公式为(rank-1)/(n-1)

CUME_DIST:
--一个5行的组中,返回的累计分布值为0.2,0.4,0.6,0.8,1.0;
--注意对于重复行,计算时取重复行中的最后一行的位置。

SELECT a.empno,
       a.ename,
       a.deptno,
       a.sal,
       percent_rank() over w as 'num',
       cume_dist() over w as 'cume'
  FROM emp a
  window w  as (PARTITION BY a.deptno ORDER BY a.sal DESC)
;
mysql> SELECT a.empno,
    ->        a.ename,
    ->        a.deptno,
    ->        a.sal,
    ->        percent_rank() over w as 'num',
    ->        cume_dist() over w as 'cume'
    ->   FROM emp a
    ->   window w  as (PARTITION BY a.deptno ORDER BY a.sal DESC);
+-------+--------+--------+---------+------+---------------------+
| empno | ename  | deptno | sal     | num  | cume                |
+-------+--------+--------+---------+------+---------------------+
|  7839 | KING   |     10 | 5000.00 |    0 |  0.3333333333333333 |
|  7782 | CLARK  |     10 | 2450.00 |  0.5 |  0.6666666666666666 |
|  7934 | MILLER |     10 | 1300.00 |    1 |                   1 |
|  7788 | SCOTT  |     20 | 3000.00 |    0 |                 0.4 |
|  7902 | FORD   |     20 | 3000.00 |    0 |                 0.4 |
|  7566 | JONES  |     20 | 2975.00 |  0.5 |                 0.6 |
|  7876 | ADAMS  |     20 | 1100.00 | 0.75 |                 0.8 |
|  7369 | SMITH  |     20 |  800.00 |    1 |                   1 |
|  7698 | BLAKE  |     30 | 2850.00 |    0 | 0.16666666666666666 |
|  7499 | ALLEN  |     30 | 1600.00 |  0.2 |  0.3333333333333333 |
|  7844 | TURNER |     30 | 1500.00 |  0.4 |                 0.5 |
|  7521 | WARD   |     30 | 1250.00 |  0.6 |  0.8333333333333334 |
|  7654 | MARTIN |     30 | 1250.00 |  0.6 |  0.8333333333333334 |
|  7900 | JAMES  |     30 |  950.00 |    1 |                   1 |
+-------+--------+--------+---------+------+---------------------+
14 rows in set (0.00 sec)

五.ntile

Ntile语法:

Ntile(expr) OVER w
window w as   ([ query_partition_clause ] order_by_clause)

Ntile 把数据行分成N个桶。每个桶会有相同的行数,正负误差为1

将员工表emp按照工资分为2、3个桶

-- 分成2个桶
SELECT ENAME, SAL, NTILE(2) OVER w as 'n' FROM EMP
window w  as (ORDER BY SAL ASC)
;

-- 分成3个桶
SELECT ENAME, SAL, NTILE(3) OVER w as 'n' FROM EMP
window w  as (ORDER BY SAL ASC)
;

mysql> -- 分成2个桶
mysql> SELECT ENAME, SAL, NTILE(2) OVER w as 'n' FROM EMP
    -> window w  as (ORDER BY SAL ASC)
    -> ;
+--------+---------+------+
| ENAME  | SAL     | n    |
+--------+---------+------+
| SMITH  |  800.00 |    1 |
| JAMES  |  950.00 |    1 |
| ADAMS  | 1100.00 |    1 |
| WARD   | 1250.00 |    1 |
| MARTIN | 1250.00 |    1 |
| MILLER | 1300.00 |    1 |
| TURNER | 1500.00 |    1 |
| ALLEN  | 1600.00 |    2 |
| CLARK  | 2450.00 |    2 |
| BLAKE  | 2850.00 |    2 |
| JONES  | 2975.00 |    2 |
| SCOTT  | 3000.00 |    2 |
| FORD   | 3000.00 |    2 |
| KING   | 5000.00 |    2 |
+--------+---------+------+
14 rows in set (0.00 sec)

mysql>
mysql> -- 分成3个桶
mysql> SELECT ENAME, SAL, NTILE(3) OVER w as 'n' FROM EMP
    -> window w  as (ORDER BY SAL ASC)
    -> ;
+--------+---------+------+
| ENAME  | SAL     | n    |
+--------+---------+------+
| SMITH  |  800.00 |    1 |
| JAMES  |  950.00 |    1 |
| ADAMS  | 1100.00 |    1 |
| WARD   | 1250.00 |    1 |
| MARTIN | 1250.00 |    1 |
| MILLER | 1300.00 |    2 |
| TURNER | 1500.00 |    2 |
| ALLEN  | 1600.00 |    2 |
| CLARK  | 2450.00 |    2 |
| BLAKE  | 2850.00 |    2 |
| JONES  | 2975.00 |    3 |
| SCOTT  | 3000.00 |    3 |
| FORD   | 3000.00 |    3 |
| KING   | 5000.00 |    3 |
+--------+---------+------+
14 rows in set (0.00 sec)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266