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或分組來進行。