天天看点

Oracle高级分析函数简介

文章目录

    • 一.row_number、rank、dense_rank
    • 二.lag、lead
    • 三.first_value、last_value、nth_value
    • 四.ratio_to_report
    • 五.percent_rank、percentile_cont、percentile_dist
    • 六.ntile

备注:测试数据库版本为Oracle 11g R2

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

scott建表及录入数据sql脚本

这个blog我们来聊聊Oracle高级分析函数

Oracle的分析函数在复杂查询以及数据仓库中应用得比较频繁

与sql打交道比较多的技术人员都需要掌握

函数名 函数用途
row_number 对行进行排序并为每一行增加一个唯一编号。这是一个非确定性函数
rank 将数据行值按照排序后的顺序进行排名,在有并列的情况下排名值将被跳过
dense_rank 将数据行值按照排序后的顺序进行排名,在有并列的情况下也不跳过排名值
lag 访问一个分区或结果集中之前的一行
lead 访问一个分区或结果集中之后的一行
first_value 访问一个分区或结果集中第一行
last_value 访问一个分区或结果集中最后一行
nth_value 访问一个分区或结果集中的任意一行
ratio_to_report 计算报告中值的比例
percent_rank 将计算得到的排名值标准化
percentile_cont 取出与指定的排名百分比相匹配的值,是percent_rank函数的反函数
percentile_dist 取出与指定的排名百分比相匹配的值,采用谨慎分布模型
ntile 将数据行分组为单元

分析函数有3个基本组成部分:

1.分区子句

2.排序子句

3.开窗子句

function1 (argument1,argument2,..argumentN)
over ([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不支持开窗子句

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(partition by a.deptno order by a.sal desc) num,
       rank() over(partition by a.deptno order by a.sal desc) rank,
       dense_rank() over(partition by a.deptno order by a.sal desc) dense_rank
  from emp a;
           
SQL> select a.empno,
  2         a.ename,
  3         a.deptno,
  4         a.sal,
  5         row_number() over(partition by a.deptno order by a.sal desc) num,
  6         rank() over(partition by a.deptno order by a.sal desc) rank,
  7         dense_rank() over(partition by a.deptno order by a.sal desc) dense_rank
  8    from emp a;
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
 7654 MARTIN         30   1250.00          4          4          4
 7521 WARD           30   1250.00          5          4          4
 7900 JAMES          30    950.00          6          6          5
14 rows selected
           

二.lag、lead

lag语法:

lag不支持开窗子句

lead同lag语法

--根据分组,取值上n条和下n条   如果是第一条或最后一条,就给个默认值
SELECT a.empno,
       a.deptno,
       a.hiredate,
       a.sal,
       lag(sal, 1, 0) over(PARTITION BY a.deptno ORDER BY hiredate ASC) pre_sal,
       lead(sal, 1, 0) over(partition by a.deptno order by hiredate asc) next_sal,
       lag(sal, 2, 0) over(PARTITION BY a.deptno ORDER BY hiredate ASC) pre2_sal,
       lead(sal, 2, 0) over(partition by a.deptno order by hiredate asc) next_2sal
  FROM emp a;
           
SQL> --根据分组,取值上n条和下n条   如果是第一条或最后一条,就给个默认值
SQL> SELECT a.empno,
  2         a.deptno,
  3         a.hiredate,
  4         a.sal,
  5         lag(sal, 1, 0) over(PARTITION BY a.deptno ORDER BY hiredate ASC) pre_sal,
  6         lead(sal, 1, 0) over(partition by a.deptno order by hiredate asc) next_sal,
  7         lag(sal, 2, 0) over(PARTITION BY a.deptno ORDER BY hiredate ASC) pre2_sal,
  8         lead(sal, 2, 0) over(partition by a.deptno order by hiredate asc) next_2sal
  9    FROM emp a;
EMPNO DEPTNO HIREDATE                             SAL    PRE_SAL   NEXT_SAL   PRE2_SAL  NEXT_2SAL
----- ------ ------------------------------ --------- ---------- ---------- ---------- ----------
 7782     10 1981/6/9 星期二                  2450.00          0       5000          0       1300
 7839     10 1981/11/17 星期二                5000.00       2450       1300          0          0
 7934     10 1982/1/23 星期六                 1300.00       5000          0       2450          0
 7369     20 1980/12/17 星期三                 800.00          0       2975          0       3000
 7566     20 1981/4/2 星期四                  2975.00        800       3000          0       3000
 7902     20 1981/12/3 星期四                 3000.00       2975       3000        800       1100
 7788     20 1987/4/19 星期日                 3000.00       3000       1100       2975          0
 7876     20 1987/5/23 星期六                 1100.00       3000          0       3000          0
 7499     30 1981/2/20 星期五                 1600.00          0       1250          0       2850
 7521     30 1981/2/22 星期日                 1250.00       1600       2850          0       1500
 7698     30 1981/5/1 星期五                  2850.00       1250       1500       1600       1250
 7844     30 1981/9/8 星期二                  1500.00       2850       1250       1250        950
 7654     30 1981/9/28 星期一                 1250.00       1500        950       2850          0
 7900     30 1981/12/3 星期四                  950.00       1250          0       1500          0
14 rows selected
           
--没有比自己小我的我们设为AAA,没有比自己大的,我们设置为ZZZ
select deptno,
       ename,
       lag(ename, 1, 'AAA') over(partition by deptno order by ename) lower_name,
       lead(ename, 1, 'ZZZ') over(partition by deptno order by ename) higher_name
  from emp;

--部门重复的话值输出第一行的部门编号  
select (case when deptno= lag(deptno,1)over(partition by deptno order by ename) then null else deptno end) deptno,
        ename,
       lag(ename, 1, 'AAA') over(partition by deptno order by ename) lower_name,
       lead(ename, 1, 'ZZZ') over(partition by deptno order by ename) higher_name
  from emp;
           
SQL> --没有比自己小我的我们设为AAA,没有比自己大的,我们设置为ZZZ
SQL> select deptno,
  2         ename,
  3         lag(ename, 1, 'AAA') over(partition by deptno order by ename) lower_name,
  4         lead(ename, 1, 'ZZZ') over(partition by deptno order by ename) higher_name
  5    from emp;
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 selected
SQL> --部门重复的话值输出第一行的部门编号
SQL> select (case when deptno= lag(deptno,1)over(partition by deptno order by ename) then null else deptno end) deptno,
  2          ename,
  3         lag(ename, 1, 'AAA') over(partition by deptno order by ename) lower_name,
  4         lead(ename, 1, 'ZZZ') over(partition by deptno order by ename) higher_name
  5    from emp;
    DEPTNO ENAME      LOWER_NAME HIGHER_NAME
---------- ---------- ---------- -----------
        10 CLARK      AAA        KING
           KING       CLARK      MILLER
           MILLER     KING       ZZZ
        20 ADAMS      AAA        FORD
           FORD       ADAMS      JONES
           JONES      FORD       SCOTT
           SCOTT      JONES      SMITH
           SMITH      SCOTT      ZZZ
        30 ALLEN      AAA        BLAKE
           BLAKE      ALLEN      JAMES
           JAMES      BLAKE      MARTIN
           MARTIN     JAMES      TURNER
           TURNER     MARTIN     WARD
           WARD       TURNER     ZZZ
14 rows selected
           

三.first_value、last_value、nth_value

first_value、last_value语法:

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

nth_value语法:

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

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


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

--rows between unbounded preceding and unbounded following 从第一行到最后一行
 select a.empno,a.deptno,to_char(hiredate,'yyyy') hiredate,a.sal,
       first_value(a.sal)  over(partition by a.deptno order by sal rows between unbounded preceding and unbounded following) first,
       last_value(a.sal) over(partition by a.deptno order by sal rows between unbounded preceding and unbounded following) last,
       nth_value(a.sal,2) over(partition by a.deptno order by sal rows between unbounded preceding and unbounded following) top_2
  from emp a; 
 
 --1 preceding and 1 following   当前行的前一行到当前行的后一行 
  select a.empno,a.deptno,to_char(hiredate,'yyyy') hiredate,a.sal,
       first_value(a.sal)  over(partition by a.deptno order by sal rows between 1 preceding and 1 following) first,
       last_value(a.sal) over(partition by a.deptno order by sal rows between 1 preceding and 1 following) last,
       nth_value(a.sal,2) over(partition by a.deptno order by sal rows between 1 preceding and 1 following top_2
  from emp a;
           
SQL> /*
  2  需求:求每个部门工资最高的和工资最低的以及工资第二高的
  3  */
SQL> --默认不带开窗子句,从第一行到当前行
SQL> select a.empno,a.deptno,to_char(hiredate,'yyyy') hiredate,a.sal,
  2         first_value(a.sal)  over(partition by a.deptno order by sal) first,
  3         last_value(a.sal) over(partition by a.deptno order by sal) last,
  4         nth_value(a.sal,2) over(partition by a.deptno order by sal) top_2
  5    from emp a;
EMPNO DEPTNO HIREDATE       SAL      FIRST       LAST      TOP_2
----- ------ -------- --------- ---------- ---------- ----------
 7934     10 1982       1300.00       1300       1300 
 7782     10 1981       2450.00       1300       2450       2450
 7839     10 1981       5000.00       1300       5000       2450
 7369     20 1980        800.00        800        800 
 7876     20 1987       1100.00        800       1100       1100
 7566     20 1981       2975.00        800       2975       1100
 7788     20 1987       3000.00        800       3000       1100
 7902     20 1981       3000.00        800       3000       1100
 7900     30 1981        950.00        950        950 
 7654     30 1981       1250.00        950       1250       1250
 7521     30 1981       1250.00        950       1250       1250
 7844     30 1981       1500.00        950       1500       1250
 7499     30 1981       1600.00        950       1600       1250
 7698     30 1981       2850.00        950       2850       1250
14 rows selected
SQL> --
SQL> --
SQL> --rows between unbounded preceding and current row  从第一行到当前行
SQL> select a.empno,a.deptno,to_char(hiredate,'yyyy') hiredate,a.sal,
  2         first_value(a.sal)  over(partition by a.deptno order by sal rows between unbounded preceding and current row) first,
  3         last_value(a.sal) over(partition by a.deptno order by sal rows between unbounded preceding and current row) last,
  4         nth_value(a.sal,2) over(partition by a.deptno order by sal rows between unbounded preceding and current row) top_2
  5    from emp a;
EMPNO DEPTNO HIREDATE       SAL      FIRST       LAST      TOP_2
----- ------ -------- --------- ---------- ---------- ----------
 7934     10 1982       1300.00       1300       1300 
 7782     10 1981       2450.00       1300       2450       2450
 7839     10 1981       5000.00       1300       5000       2450
 7369     20 1980        800.00        800        800 
 7876     20 1987       1100.00        800       1100       1100
 7566     20 1981       2975.00        800       2975       1100
 7788     20 1987       3000.00        800       3000       1100
 7902     20 1981       3000.00        800       3000       1100
 7900     30 1981        950.00        950        950 
 7654     30 1981       1250.00        950       1250       1250
 7521     30 1981       1250.00        950       1250       1250
 7844     30 1981       1500.00        950       1500       1250
 7499     30 1981       1600.00        950       1600       1250
 7698     30 1981       2850.00        950       2850       1250
14 rows selected
SQL> --
SQL> --
SQL> --rows between unbounded preceding and unbounded following 从第一行到最后一行
SQL>  select a.empno,a.deptno,to_char(hiredate,'yyyy') hiredate,a.sal,
  2         first_value(a.sal)  over(partition by a.deptno order by sal rows between unbounded preceding and unbounded following) first,
  3         last_value(a.sal) over(partition by a.deptno order by sal rows between unbounded preceding and unbounded following) last,
  4         nth_value(a.sal,2) over(partition by a.deptno order by sal rows between unbounded preceding and unbounded following) top_2
  5    from emp a;
EMPNO DEPTNO HIREDATE       SAL      FIRST       LAST      TOP_2
----- ------ -------- --------- ---------- ---------- ----------
 7934     10 1982       1300.00       1300       5000       2450
 7782     10 1981       2450.00       1300       5000       2450
 7839     10 1981       5000.00       1300       5000       2450
 7369     20 1980        800.00        800       3000       1100
 7876     20 1987       1100.00        800       3000       1100
 7566     20 1981       2975.00        800       3000       1100
 7788     20 1987       3000.00        800       3000       1100
 7902     20 1981       3000.00        800       3000       1100
 7900     30 1981        950.00        950       2850       1250
 7654     30 1981       1250.00        950       2850       1250
 7521     30 1981       1250.00        950       2850       1250
 7844     30 1981       1500.00        950       2850       1250
 7499     30 1981       1600.00        950       2850       1250
 7698     30 1981       2850.00        950       2850       1250
14 rows selected
SQL> --
SQL> --
SQL>  --1 preceding and 1 following   当前行的前一行到当前行的后一行
SQL>   select a.empno,a.deptno,to_char(hiredate,'yyyy') hiredate,a.sal,
  2         first_value(a.sal)  over(partition by a.deptno order by sal rows between 1 preceding and 1 following) first,
  3         last_value(a.sal) over(partition by a.deptno order by sal rows between 1 preceding and 1 following) last,
  4         nth_value(a.sal,2) over(partition by a.deptno order by sal rows between 1 preceding and 1 following) top_2
  5    from emp a;
EMPNO DEPTNO HIREDATE       SAL      FIRST       LAST      TOP_2
----- ------ -------- --------- ---------- ---------- ----------
 7934     10 1982       1300.00       1300       2450       2450
 7782     10 1981       2450.00       1300       5000       2450
 7839     10 1981       5000.00       2450       5000       5000
 7369     20 1980        800.00        800       1100       1100
 7876     20 1987       1100.00        800       2975       1100
 7566     20 1981       2975.00       1100       3000       2975
 7788     20 1987       3000.00       2975       3000       3000
 7902     20 1981       3000.00       3000       3000       3000
 7900     30 1981        950.00        950       1250       1250
 7654     30 1981       1250.00        950       1250       1250
 7521     30 1981       1250.00       1250       1500       1250
 7844     30 1981       1500.00       1250       1600       1500
 7499     30 1981       1600.00       1500       2850       1600
 7698     30 1981       2850.00       1600       2850       2850
14 rows selected
           

四.ratio_to_report

ratio_to_report语法:

测试数据:

DROP TABLE testa;
 
 
CREATE  TABLE testa (area   VARCHAR2 (20), month VARCHAR2   (20),
amount NUMBER);


insert into testa values ('上海', '1月', 199); 
insert into testa values ('上海', '2月', 199); 
insert into testa values ('上海', '3月', 155); 
insert into testa values ('上海', '3月', 155); 
insert into testa values ('上海', '4月', 125); 
insert into testa values ('广州', '1月', 75); 
insert into testa values ('广州', '2月', 67); 
insert into testa values ('北京', '1月', 235);
insert into testa values ('北京', '2月', 330); 
Commit;
           
--求每个月销售额占比
SELECT area,
       MONTH,
       SUM(amount) amount,
       ROUND(ratio_to_report(SUM(amount)) OVER(PARTITION BY area), 4) * 100 area_pct
  FROM testa
 GROUP BY area, MONTH;
           
SQL> --求每个月销售额占比
SQL> SELECT area,
 2         MONTH,
 3         SUM(amount) amount,
 4         ROUND(ratio_to_report(SUM(amount)) OVER(PARTITION BY area), 4) * 100 area_pct
 5    FROM testa
 6   GROUP BY area, MONTH;
AREA                 MONTH                    AMOUNT   AREA_PCT
-------------------- -------------------- ---------- ----------
北京                 1月                         235      41.59
北京                 2月                         330      58.41
广州                 1月                          75      52.82
广州                 2月                          67      47.18
上海                 1月                         199      23.89
上海                 2月                         199      23.89
上海                 3月                         310      37.21
上海                 4月                         125      15.01
8 rows selected
           

五.percent_rank、percentile_cont、percentile_dist

percent_rank语法:

percent_rank(expr) within group (order-by-clause )
percent_rank() over ([partition-by-clause] [order-by-clause] )
           

PERCENTILE_CONT语法:

PERCENTILE_DISC语法:

–percent_rank函数以0到1之间的分数形式返回某个值在数据分区中的排名

–percent_rank的计算公式为(rank-1)/(n-1)

SELECT a.empno,
       a.ename,
       a.deptno,
       a.sal,
       percent_rank() over(PARTITION BY a.deptno ORDER BY a.sal DESC) num
  FROM emp a;
           
SQL> SELECT a.empno,
  2         a.ename,
  3         a.deptno,
  4         a.sal,
  5         percent_rank() over(PARTITION BY a.deptno ORDER BY a.sal DESC) num
  6    FROM emp a;
EMPNO ENAME      DEPTNO       SAL        NUM
----- ---------- ------ --------- ----------
 7839 KING           10   5000.00          0
 7782 CLARK          10   2450.00        0.5
 7934 MILLER         10   1300.00          1
 7788 SCOTT          20   3000.00          0
 7902 FORD           20   3000.00          0
 7566 JONES          20   2975.00        0.5
 7876 ADAMS          20   1100.00       0.75
 7369 SMITH          20    800.00          1
 7698 BLAKE          30   2850.00          0
 7499 ALLEN          30   1600.00        0.2
 7844 TURNER         30   1500.00        0.4
 7654 MARTIN         30   1250.00        0.6
 7521 WARD           30   1250.00        0.6
 7900 JAMES          30    950.00          1
14 rows selected
           

–percentile_cont

–如计算一个城市或地区中等收入家庭的收入值,中位值是percent_rank为0.5

–percentile_cont(0.5)子句将会返回中位值,如果没有0.5,则取值上下最接近的2个值求平均值

SELECT ename,
       sal,
       deptno,
       PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY sal DESC) OVER(PARTITION BY deptno) "Percentile_Cont",
       PERCENT_RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) "Percent_Rank"
  FROM emp
 ORDER BY deptno,sal desc;
           
SQL> SELECT ename,
  2         sal,
  3         deptno,
  4         PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY sal DESC) OVER(PARTITION BY deptno) "Percentile_Cont",
  5         PERCENT_RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) "Percent_Rank"
  6    FROM emp
  7   ORDER BY deptno,sal desc;
ENAME            SAL DEPTNO Percentile_Cont Percent_Rank
---------- --------- ------ --------------- ------------
KING         5000.00     10            2450            0
CLARK        2450.00     10            2450          0.5
MILLER       1300.00     10            2450            1
SCOTT        3000.00     20            2975            0
FORD         3000.00     20            2975            0
JONES        2975.00     20            2975          0.5
ADAMS        1100.00     20            2975         0.75
SMITH         800.00     20            2975            1
BLAKE        2850.00     30            1375            0
ALLEN        1600.00     30            1375          0.2
TURNER       1500.00     30            1375          0.4
WARD         1250.00     30            1375          0.6
MARTIN       1250.00     30            1375          0.6
JAMES         950.00     30            1375            1
14 rows selected

SQL> 
           

–percentile_disc

percentile_disc函数在功能上类似percentile_cont函数,只是percentile_cont函数使用了连续分布模型,而percentile_disc函数使用了离散分布模型。

SELECT ename,
       sal,
       deptno,
       PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY sal DESC) OVER(PARTITION BY deptno) "Percentile_Cont",
       PERCENTILE_DISC(0.5) WITHIN GROUP(ORDER BY sal DESC) OVER(PARTITION BY deptno) "Percentile_Disc",
       PERCENT_RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) "Percent_Rank"
  FROM emp
 ORDER BY deptno,sal desc;
           
SQL> SELECT ename,
  2         sal,
  3         deptno,
  4         PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY sal DESC) OVER(PARTITION BY deptno) "Percentile_Cont",
  5         PERCENTILE_DISC(0.5) WITHIN GROUP(ORDER BY sal DESC) OVER(PARTITION BY deptno) "Percentile_Disc",
  6         PERCENT_RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) "Percent_Rank"
  7    FROM emp
  8   ORDER BY deptno,sal desc;
ENAME            SAL DEPTNO Percentile_Cont Percentile_Disc Percent_Rank
---------- --------- ------ --------------- --------------- ------------
KING         5000.00     10            2450            2450            0
CLARK        2450.00     10            2450            2450          0.5
MILLER       1300.00     10            2450            2450            1
SCOTT        3000.00     20            2975            2975            0
FORD         3000.00     20            2975            2975            0
JONES        2975.00     20            2975            2975          0.5
ADAMS        1100.00     20            2975            2975         0.75
SMITH         800.00     20            2975            2975            1
BLAKE        2850.00     30            1375            1500            0
ALLEN        1600.00     30            1375            1500          0.2
TURNER       1500.00     30            1375            1500          0.4
WARD         1250.00     30            1375            1500          0.6
MARTIN       1250.00     30            1375            1500          0.6
JAMES         950.00     30            1375            1500            1
14 rows selected
           

六.ntile

Ntile语法:

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

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

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

--分成3个桶
SELECT ENAME, SAL, NTILE(3) OVER (ORDER BY SAL ASC ) FROM EMP;
           
SQL> --分成2个桶
SQL> SELECT ENAME, SAL, NTILE(2) OVER (ORDER BY SAL ASC ) FROM EMP;
ENAME            SAL NTILE(2)OVER(ORDERBYSALASC)
---------- --------- ---------------------------
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 selected
SQL> --分成3个桶
SQL> SELECT ENAME, SAL, NTILE(3) OVER (ORDER BY SAL ASC ) FROM EMP;
ENAME            SAL NTILE(3)OVER(ORDERBYSALASC)
---------- --------- ---------------------------
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 selected
           

继续阅读