分析函數2之(Top/Bottom N、First/Last、NTile)

目錄

1.帶空值的排列
2.Top/Bottom N查詢
3.First/Last排名查詢
4.按層次查詢

一、帶空值的排列

       解決排列的數據中含有空值的。NULL爲最大值,這是我們不想見到的!

SQL> select deptno,ename,sum(sal) sal_sum,
                   sum(sum(sal)) over (partition by deptno ) total,
                    rank () over (partition by deptno order by sum(sal) desc) rank
           from emp group by deptno,ename;
 
DEPTNO ENAME  SAL_SUM      TOTAL       RANK
------ ---------- ---------- ---------- ----------
    10 KING                   5000    8564.59          1
    10 CLARK               2450    8564.59          2
    10 MILLER         1114.59    8564.59         3
    20 SCOTT                3000     9953.8          1
    20 FORD                  3000     9953.8          1
    20 JONES             2053.8     9953.8          3
    20 ADAMS                1100     9953.8          4
    20 SMITH                   800      9953.8          5
    30 JAMES                                  8450          1
    30 BLAKE                2850         8450          2
    30 ALLEN                1600         8450          3
    30 TURNER            1500         8450          4
    30 WARD                 1250         8450          5
    30 MARTIN               1250         8450          5
 
14 rows selected

下面修改後:

SQL> select deptno,ename,sum(sal) sal_sum,
                   sum(sum(sal)) over (partition by deptno ) total,
                    rank () over (partition by deptno order by sum(sal) desc  NULLS LAST ) rank
           from emp group by deptno,ename;
 
DEPTNO ENAME         SAL_SUM      TOTAL       RANK
------ ---------- ---------- ---------- ----------
    10 KING             5000    8564.59             1
    10 CLARK            2450    8564.59            2
    10 MILLER        1114.59    8564.59           3
    20 SCOTT            3000     9953.8             1
    20 FORD             3000     9953.8          1
    20 JONES          2053.8     9953.8          3
    20 ADAMS            1100     9953.8          4
    20 SMITH             800     9953.8          5
    30 BLAKE            2850       8450          1
    30 ALLEN            1600       8450          2
    30 TURNER           1500       8450          3
    30 WARD             1250       8450          4
    30 MARTIN           1250       8450          4
    30 JAMES                              8450          6
 
14 rows selected

NULLS LAST/FIRST告訴Oracle讓空值排名最後後第一。

注意是NULLS,不是NULL。

 

二、Top/Bottom N查詢:

      在日常生活中我們經常會遇到這樣的查詢,找出工資前五名的人員。

SQL> select t.*, rownum from (select * from emp order by sal desc) t where rownum<5;
 
EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO     ROWNUM
----- ---------- --------- ----- ----------- --------- --------- ------ ----------
 7900 JAMES      CLERK        7698    1981-12-03                                      30          1
 7839 KING       PRESIDENT              1981-11-17    5000.00                   10          2
 7788 SCOTT    ANALYST     7566    1987-04-19    3000.00                    20          3
 7902 FORD       ANALYST    7566    1981-12-03    3000.00                    20          4

   以上爲子查詢對sal進行排序,SAL空值用前面的方法解決

SQL> select t.*, rownum from (select * from emp order by sal desc NULLS LAST) t where rownum<5;
 
EMPNO ENAME      JOB         MGR HIREDATE          SAL  COMM DEPTNO     ROWNUM
----- ---------- --------- ----- ----------- --------- --------- ------ ----------
 7839 KING       PRESIDENT           1981-11-17    5000.00               10               1
 7788 SCOTT      ANALYST    7566 1987-04-19    3000.00               20               2
 7902 FORD       ANALYST     7566 1981-12-03    3000.00               20               3
 7698 BLAKE      MANAGER   7839 1981-05-01    2850.00               30               4
  以上爲前4名的排列結果

使用分析函數操作如下:

SQL> select * from (select t.*,rank() over (order by sal desc NULLS LAST) rank from emp t) a where rownum<5 ;
 
EMPNO ENAME      JOB            MGR         HIREDATE          SAL  COMM DEPTNO       RANK
----- ---------- --------- ----- ----------- --------- --------- ------ ----------
 7839     KING       PRESIDENT                 1981-11-17    5000.00               10          1
 7902     FORD       ANALYST       7566     1981-12-03    3000.00               20          2
 7788     SCOTT      ANALYST      7566     1987-04-19    3000.00               20          2
 7698     BLAKE      MANAGER    7839      1981-05-01    2850.00               30          4

以上爲爲分析函數操作結果

三、First/Last排名查詢:
找出按部門分組工資總計,最高工資是多少,與最低工資是多少.

SQL> select deptno, sum(sal),
                   min(sal) keep(dense_rank first order by sal desc nulls last ) first,
                   min(sal) keep(dense_rank last order by sal desc ) last
           from emp group by deptno order by deptno;
 
DEPTNO   SUM(SAL)      FIRST       LAST
------ ---------- ---------- ----------
    10           8564.59           5000      1114.59
    20           9953.8             3000        800
    30           8450                2850       1250

SQL> select max(sal),min(sal) from emp;
 
  MAX(SAL)   MIN(SAL)
---------- ----------
      5000        800

這裏有幾個看起來比較疑惑的地方:

①爲什麼這裏要用min函數
②Keep這個東西是幹什麼的
③fist/last是幹什麼的
④dense_rank和dense_rank()有什麼不同,能換成rank嗎?

首先解答一下第一個問題:min函數的作用是用於當存在多個First/Last情況下保證返回唯一的記錄。假如我們去掉會有什麼樣的後果呢?

    select deptno, sum(sal),
         keep(dense_rank first order by sal desc nulls last ) first,
          keep(dense_rank last order by sal desc ) last
    from emp group by deptno order by deptno


 keep(dense_rank first order by sal desc nulls last ) first,
                                  *
ORA-00907: missing right parenthesis

接下來看看第2個問題:keep是幹什麼用的?從上面的結果我們已經知道Oracle對排名的結果只“保留”2條數據,這就是keep的作用。告訴Oracle只保留符合keep條件的記錄。

那麼什麼纔是符合條件的記錄呢?這就是第3個問題了。dense_rank是告訴Oracle排列的策略,first/last則告訴最終篩選的條件。

第4個問題:如果我們把dense_rank換成rank呢?

select deptno, sum(sal),
        max(sal)   keep(rank first order by sal desc nulls last ) first,
        max(sal)   keep(rank last order by sal desc ) last
  from emp group by deptno order by deptno

       max(sal)   keep(rank first order by sal desc nulls last ) first,
                                     *

ORA-02000: missing DENSE_RANK keyword

 

 四、按層次查詢:
    統計出工資前1/5之的人員的名單.使用NTILE分析函數,把所有工資分爲5份,爲1的哪一份就是我們想要的結果:

SQL> select empno,ename,sum(sal),
                ntile(5) over (order by sum(sal) desc nulls last) til
           from emp
           group by empno,ename;

EMPNO ENAME        SUM(SAL)        TIL
----- ---------- ---------- ----------
 7839 KING                5000                 1
 7788 SCOTT            3000                 1
 7902 FORD              3000                 1
 7698 BLAKE             2850                 2
 7782 CLARK            2450                 2
 7566 JONES           2053.8               2
 7499 ALLEN            1600                  3
 7844 TURNER        1500                  3
 7521 WARD             1250                  3
 7654 MARTIN          1250                  4
 7934 MILLER        1114.59               4
 7876 ADAMS            1100                 4
 7369 SMITH               800                  5
 7900 JAMES                                        5
 
14 rows selected
 

如果需要找出前25%的用戶資料,哪就只需要NTILE(4)就可以了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章