oracle下資料的排序分組row_number() over()--分析函式,可用於去重

perfychi發表於2014-12-28

From:http://heshw.blog.51cto.com/5891747/1275140/
oracle下資料的排序分組row_number() over()--分析函式,可用於去重

   row_number()over(partition by col1 order by col2)表示根據col1分組,在分組內部根據col2排序,而此函式計算的值就表示每組內部排序後的順序編號(組內連續的唯一的)。 
與rownum的區別在於:使用rownum進行排序的時候是先對結果集加入偽劣rownum然後再進行排序,而此函式在包含排序從句後是先排序再計算行號碼。


   與此功能相似的函式還有:rank/dense_rank/ntile

row_number()和rownum差不多,功能更強一點(可以在各個分組內從1開始排序)。 
rank()是跳躍排序,有兩個第二名時接下來就是第四名(同樣是在各個分組內) 
dense_rank()也是連續排序,有兩個第二名時仍然跟著第三名。相比之下row_number是沒有重複值的

oracle 分析函式 row_number(),返回一個整數值(>=1)


測試表/資料

CREATE TABLE test_course (

 student_name  VARCHAR(10),  -- 學生

 course_name   VARCHAR(10),  -- 課程

 grade         INT           -- 成績

);



INSERT INTO test_course VALUES('甲', '語文', 95);

INSERT INTO test_course VALUES('乙', '語文', 85);

INSERT INTO test_course VALUES('丙', '語文', 75);

INSERT INTO test_course VALUES('丁', '語文', 65);

INSERT INTO test_course VALUES('戊', '語文', 55);

INSERT INTO test_course VALUES('己', '語文', 50);

INSERT INTO test_course VALUES('庚', '語文', 60);

INSERT INTO test_course VALUES('辛', '語文', 70);

INSERT INTO test_course VALUES('壬', '語文', 80);

INSERT INTO test_course VALUES('奎', '語文', 90);


INSERT INTO test_course VALUES('甲', '數學', 90);

INSERT INTO test_course VALUES('乙', '數學', 80);

INSERT INTO test_course VALUES('丙', '數學', 70);

INSERT INTO test_course VALUES('丁', '數學', 60);

INSERT INTO test_course VALUES('戊', '數學', 50);

INSERT INTO test_course VALUES('己', '數學', 50);

INSERT INTO test_course VALUES('庚', '數學', 60);

INSERT INTO test_course VALUES('辛', '數學', 70);

INSERT INTO test_course VALUES('壬', '數學', 85);

INSERT INTO test_course VALUES('奎', '數學', 95);




ROW_NUMBER 順序編號


按照分數 編號 從高到底

SELECT

 ROW_NUMBER() OVER( ORDER BY SUM(grade) DESC) AS NO,

 student_name,

 SUM(grade) AS AllGrade

FROM

 test_course

GROUP BY

 student_name

ORDER BY

 SUM(grade) DESC


1 甲 185

2 奎 185

3 壬 165

4 乙 165

5 丙 145

6 辛 140

7 丁 125

8 庚 120

9 戊 105

10 己 100



按照分數 編號 從高到底(區分 課程)


SELECT

 ROW_NUMBER() OVER(PARTITION BY course_name ORDER BY grade DESC) AS NO,

 *

FROM

 test_course

ORDER BY

 course_name,

 grade DESC


1 奎 數學 95

2 甲 數學 90

3 壬 數學 85

4 乙 數學 80

5 丙 數學 70

6 辛 數學 70

7 庚 數學 60

8 丁 數學 60

9 戊 數學 50

10 己 數學 50

1 甲 語文 95

2 奎 語文 90

3 乙 語文 85

4 壬 語文 80

5 丙 語文 75

6 辛 語文 70

7 丁 語文 65

8 庚 語文 60

9 戊 語文 55

10 己 語文 50




RANK 排名不連續


按照分數 排名 從高到底

SELECT

 RANK() OVER( ORDER BY SUM(grade) DESC) AS NO,

 student_name,

 SUM(grade) AS AllGrade

FROM

 test_course

GROUP BY

 student_name

ORDER BY

 SUM(grade) DESC


1 甲 185

1 奎 185

3 壬 165

3 乙 165

5 丙 145

6 辛 140

7 丁 125

8 庚 120

9 戊 105

10 己 100


按照分數 排名 從高到底(區分 課程)


SELECT

 RANK() OVER(PARTITION BY course_name ORDER BY grade DESC) AS NO,

 *

FROM

 test_course

ORDER BY

 course_name,

 grade DESC


1 奎 數學 95

2 甲 數學 90

3 壬 數學 85

4 乙 數學 80

5 丙 數學 70

5 辛 數學 70

7 庚 數學 60

7 丁 數學 60

9 戊 數學 50

9 己 數學 50

1 甲 語文 95

2 奎 語文 90

3 乙 語文 85

4 壬 語文 80

5 丙 語文 75

6 辛 語文 70

7 丁 語文 65

8 庚 語文 60

9 戊 語文 55

10 己 語文 50




DENSE_RANK 排名連續


按照分數 排名 從高到底


SELECT

 DENSE_RANK() OVER( ORDER BY SUM(grade) DESC) AS NO,

 student_name,

 SUM(grade) AS AllGrade

FROM

 test_course

GROUP BY

 student_name

ORDER BY

 SUM(grade) DESC


1 甲 185

1 奎 185

2 壬 165

2 乙 165

3 丙 145

4 辛 140

5 丁 125

6 庚 120

7 戊 105

8 己 100


按照分數 排名 從高到底(區分 課程)

SELECT

 DENSE_RANK() OVER(PARTITION BY course_name ORDER BY grade DESC) AS NO, *

FROM

 test_course

ORDER BY

 course_name,

 grade DESC


1 奎 數學 95

2 甲 數學 90

3 壬 數學 85

4 乙 數學 80

5 丙 數學 70

5 辛 數學 70

6 庚 數學 60

6 丁 數學 60

7 戊 數學 50

7 己 數學 50

1 甲 語文 95

2 奎 語文 90

3 乙 語文 85

4 壬 語文 80

5 丙 語文 75

6 辛 語文 70

7 丁 語文 65

8 庚 語文 60

9 戊 語文 55

10 己 語文 50




NTILE 分組


按照分數 劃分5個區間 從高到底

SELECT

 NTILE(5) OVER( ORDER BY SUM(grade) DESC) AS NO,

 student_name,

 SUM(grade) AS AllGrade

FROM

 test_course

GROUP BY

 student_name

ORDER BY

 SUM(grade) DESC


1 甲 185

1 奎 185

2 壬 165

2 乙 165

3 丙 145

3 辛 140

4 丁 125

4 庚 120

5 戊 105

5 己 100


按照分數 劃分割槽間 從高到底(區分 課程)

SELECT

 NTILE(5) OVER(PARTITION BY course_name ORDER BY grade DESC) AS NO,

 *

FROM

 test_course

ORDER BY

 course_name,

 grade DESC


1 奎 數學 95

1 甲 數學 90

2 壬 數學 85

2 乙 數學 80

3 丙 數學 70

3 辛 數學 70

4 庚 數學 60

4 丁 數學 60

5 戊 數學 50

5 己 數學 50

1 甲 語文 95

1 奎 語文 90

2 乙 語文 85

2 壬 語文 80

3 丙 語文 75

3 辛 語文 70

4 丁 語文 65

4 庚 語文 60

5 戊 語文 55

5 己 語文 50


   使用分析函式來進行去重的例子:

product loid time
aaa AAABBBCCC 2013-4-5
aaa CCC55SSADD 2013-4-13
bbb FFFF223SSSA 2013-8-8
bbb GSAAASSFBB 2013-8-1


   資料結構如上圖,其中第1列有重複,第2列唯一,第3列為時間,有大小唯一。需求:一個product只能有一個loid,現需要根據時間大小,保留最後一次增加的資料,將時間小的product刪除。最後得到結果如下:

product loid time
aaa CCC55SSADD 2013-4-13
bbb FFFF223SSSA 2013-8-8

   思路:根據product來進行分組編號,透過時間大小來排序。篩選出時間最大的loid,再根據loid將product重複的刪除)

select row_number() over(partition by product order by time desc) as no,product,loid,time from test;    --透過分析函式進行分組編號

select loid from (select row_number() over(partition by product order by time desc) as no,product,loid,time from test) where no=1;  ---得出滿足條件的loid,因為為降序,所以不管product重複的有幾個,編號為1的始終為分組內時間最大的

delete from test where loid not in (select loid from (select row_number() over(partition by product order by time desc) as no,product,loid,time from test) where no=1);    --根據得出的滿足條件的loid來進行篩選刪除。


   此為透過分析函式來去重的例子,其他重複資料的查詢與刪除,可透過rowid或分組來進行。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/27042095/viewspace-1383187/,如需轉載,請註明出處,否則將追究法律責任。

相關文章