Oracle從8i開始就提供了3個分析函數:rank,dense_rank,row_number(1)Rank函數返回一個唯一的值,除非遇到相同的數據時,此時所有相同數據的排名是一樣的, 同時會在最后一條相同記錄和下一條不同記錄的排名之間空出排名。 (2)Dense_rank函數返回一個唯一的值,除非當碰到相同數據時,此時所有相同數據的排名都是一樣的。(3)Row_number函數返回一個唯一的值,當碰到相同數據時,排名按照記錄集中記錄的順序依次遞增。例:create table s_score( s_id number(6) ,score number(4,2));insert into s_score values(001,98);insert into s_score values(002,66.5);insert into s_score values(003,99);insert into s_score values(004,98);insert into s_score values(005,98);insert into s_score values(006,80);select s_id ,score ,rank() over(order by score desc) rank ,dense_rank() over(order by score desc) dense_rank ,row_number() over(order by score desc) row_numberfrom s_score; S_ID SCORE RANK DENSE_RANK ROW_NUMBER------- ------ ---------- ---------- ---------- 3 99.00 1 1 1 1 98.00 2 2 2 4 98.00 2 2 3 5 98.00 2 2 4 6 80.00 5 3 5 2 66.50 6 4 6 排名/排序的時候,有時候,我們會想到利用偽列rownum,利用rownum確實可以解決某些場景下的問題(但是相對也比較復雜),而且有些場景下的問題卻很難解決。例:取成績前三名,并且前三名含有并列的情況 通過上面例子,我們可以直觀的看到,結果應該有5條記錄。select s_id ,score ,dense_rankfrom (select s_id ,score ,rank() over(order by score desc) rank ,dense_rank() over(order by score desc) dense_rank ,row_number() over(order by score desc) row_numberfrom s_score) twhere dense_rank <= 3; S_ID SCORE DENSE_RANK------- ------ ---------- 3 99.00 1 1 98.00 2 5 98.00 2 4 98.00 2 6 80.00 3 如果只是簡單的想到去用rownum <= 3 得到的結果顯然不可能是正確的。組內的排名或者排序是經常遇到的一種場景。例如,取每個銷售部門內,銷售業績最好的前三名。 取每個班級內成績排名信息等等.. 取每個班級內每門課成績排名第一的同學信息 drop table S_SCORE;create table S_SCORE( S_ID NUMBER(6), CLASS_ID VARCHAR2(2), COURSE VARCHAR2(20), SCORE NUMBER(5,2));INSERT INTO S_SCORE VALUES(1001,'A','MATH','67');INSERT INTO S_SCORE VALUES(1004,'B','MATH','88');INSERT INTO S_SCORE VALUES(1002,'A','MATH','99');INSERT INTO S_SCORE VALUES(1003,'A','MATH','55');INSERT INTO S_SCORE VALUES(1001,'B','MATH','88');INSERT INTO S_SCORE VALUES(1001,'B','MATH','70');INSERT INTO S_SCORE VALUES(1001,'A','ORACLE','97');INSERT INTO S_SCORE VALUES(1004,'B','ORACLE','48');INSERT INTO S_SCORE VALUES(1002,'A','ORACLE','79');INSERT INTO S_SCORE VALUES(1003,'A','ORACLE','65');INSERT INTO S_SCORE VALUES(1001,'B','ORACLE','82');INSERT INTO S_SCORE VALUES(1001,'B','ORACLE','78');select s_id ,class_id ,course ,score ,dense_rank() over (partition by class_id,course order by score desc) drkfrom S_SCORE; S_ID CLASS_ID COURSE SCORE DRK------- -------- -------------------- ------- ---------- 1002 A MATH 99.00 1 1001 A MATH 67.00 2 1003 A MATH 55.00 3 1001 A ORACLE 97.00 1 1002 A ORACLE 79.00 2 1003 A ORACLE 65.00 3 1004 B MATH 88.00 1 1001 B MATH 88.00 1 1001 B MATH 70.00 2 1001 B ORACLE 82.00 1 1001 B ORACLE 78.00 2 1004 B ORACLE 48.00 3 select s_id ,class_id ,course ,scorefrom (select s_id ,class_id ,course ,score ,dense_rank() over (partition by class_id,course order by score desc) drkfrom S_SCORE) twhere drk = 1; S_ID CLASS_ID COURSE SCORE------- -------- -------------------- ------- 1002 A MATH 99.00 1001 A ORACLE 97.00 1004 B MATH 88.00 1001 B MATH 88.00 1001 B ORACLE 82.00 rank()和dense_rank()用法相似,這里就不在舉例說明了。可以將上面的例子中dense_rank()替換成rank()實現。接下來,看一個使用row_number()的場景例:查看每個部門最近一筆銷售記錄select * from criss_sales order by dept_id,sale_date desc;DEPT_ID SALE_DATE GOODS_TYPE SALE_CNT------- ----------- ---------- -----------D01 2014/5/4 G02 80D01 2014/4/30 G03 800D01 2014/4/8 G01 200D01 2014/3/4 G00 700D02 2014/5/2 G03 900D02 2014/4/27 G01 300D02 2014/4/8 G02 100D02 2014/3/6 G00 500即,我們希望得到D01 2014/5/4 G02 80D02 2014/5/2 G03 900這兩條記錄select dept_id ,sale_date ,goods_type ,sale_cnt ,row_number() over (partition by dept_id order by sale_date desc)from criss_sales;DEPT_ID SALE_DATE GOODS_TYPE SALE_CNT ROW_NUMBER()OVER(PARTITIONBYDE------- ----------- ---------- ----------- ------------------------------D01 2014/5/4 G02 80 1D01 2014/4/30 G03 800 2D01 2014/4/8 G01 200 3D01 2014/3/4 G00 700 4D02 2014/5/2 G03 900 1D02 2014/4/27 G01 300 2D02 2014/4/8 G02 100 3D02 2014/3/6 G00 500 4select dept_id ,sale_date ,goods_type ,sale_cntfrom (select dept_id ,sale_date ,goods_type ,sale_cnt ,row_number() over (partition by dept_id order by sale_date desc) rnfrom criss_sales) twhere rn = 1;DEPT_ID SALE_DATE GOODS_TYPE SALE_CNT------- ----------- ---------- -----------D01 2014/5/4 G02 80D02 2014/5/2 G03 900-----------------------------------------------------------------------------------------------------------------在部門內新水排名(如果有相同名次,用dense_rank)SELECT row_number() over(PARTITION BY t.deptno --按部門分組ORDER BY t.sal) rn, --部門內按薪水排序 t.sal, t.ename, t.deptno FROM emp t;--分組累計計數,注意相同sal情況SELECT COUNT(*) over(PARTITION BY t.deptno ORDER BY sal) cn, t.sal, t.ename, t.deptno FROM emp t;一、排名函數1>、計算行號ROW_NUMBER函數2>、排名和密集排號RANK和DESN_RANK--示例:CREATE TABLE dbo.Sales( empid VARCHAR(10) NOT NULL PRIMARY KEY, mgrid VARCHAR(10) NOT NULL, qty INT NOT NULL);INSERT INTO dbo.Sales(empid, mgrid, qty) VALUES ('A', 'Z', 300), ('B', 'X', 100), ('C', 'X', 200), ('D', 'Y', 200), ('E', 'Z', 250), ('F', 'Z', 300), ('G', 'X', 100), ('H', 'Y', 150), ('I', 'X', 250), ('J', 'Z', 100), ('K', 'Y', 200);CREATE INDEX idx_qty_empid ON dbo.Sales(qty, empid);CREATE INDEX idx_mgrid_qty_empid ON dbo.Sales(mgrid, qty, empid);GO###對比###select ROW_NUMBER() OVER (ORDER BY qty) AS seq,RANK()OVER (ORDER BY qty) AS seq1, DENSE_RANK() OVER (ORDER BY qty) AS seq2, *FROM Sales s --運行結果seq seq1 seq2 empid mgrid qty1 1 1 B X 1002 1 1 G X 1003 1 1 J Z 1004 4 2 H Y 1505 5 3 C X 2006 5 3 D Y 2007 5 3 K Y 2008 8 4 E Z 2509 8 4 I X 25010 10 5 A Z 30011 10 5 F Z 300區別:當order by 列表不能唯一決定排序順序時,ROW_NUMBER是非確定性的。而RANK和DENSE_RANK總是確定性的。即,具有相同排序值的行總是得到相同的排名值。而RANK和DENSE_RANK的區別在于,RANK生成的排名值可能有間斷,但可以表明有多少行具有更低的排序值。DENSE_RANK生成的排名值沒有間斷。--分析函數:count(a) over (partition by b order by c)--上面的count()就是一個分析函數;over可以理解為一個關鍵字或者標識,有over就表示它前面的函數--是一個分析函數,否則就是普通的求和函數了;--()中的partition by是指定分區,或者理解為分組--()中的order by是指定該分區內的數據的順序參考:http://jingyan.baidu.com/article/597035521ff2ec8fc107404b.html