GROUP BY TOP N應用情境,grouptop
因為工作原因,前段時間遇到這樣的問題遊戲角色合服,但是每個區服下同一個帳號只能保留3個角色,那麼問題來了,挖掘機技術那家強?
可能有的同學還是沒明白這是怎樣的應用情境,舉個例子:
上面資料情境從,現在要求單科前兩名同學的成績。
現在怎麼來解決這樣的問題?
通過分析可知,我們現在是要在每一科兩面找到前2位成績排名的資訊。
很遺憾的告訴大家,其實Oracle和MSSQL都是有內建函數rownumber() over(partition by col1 order by col2)
row_number()和rownum差不多,功能更強一點(可以在各個分組內從1開時排序);
rank()是跳躍排序,有兩個第二名時接下來就是第四名(同樣是在各個分組內);
dense_rank()l是連續排序,有兩個第二名時仍然跟著第三名。相比之下row_number是沒有重複值的.
MySQL好像還沒這樣的函數,Over函數都沒,如果你願意的話可以寫了一個Over函數,但是這裡就不討論了,我只說一個能直接查詢的語句。
SELECT * FROM ( select *,@num := if(@group = `course`, @num + 1, 1) as row_number,@group := course as sub_group
from Points order by course,point desc) as x
WHERE x.row_number<=2;
SQL中有幾點要給大家說明一下@num相當於我們自己給的一個排序碼,然後這個排序碼是根據sub_group來分隔的,也就是說一個group裡面都有一個唯一不重複的排序碼,有了這個排序碼過後我們最後在這個大的結果集裡面就可以用這個排序碼作為前幾名同學的篩選條件出最後的資料了。
注意一點,這裡在每個分組裡面的我的排序碼是全自增的,沒有實現前面rank()和dense_rank()這樣的功能。
既然都說了MSSQL有這樣的函數總要拉出來溜溜啥。
SELECT [name],[course],[point]
FROM
(SELECT [name],[course],[point],
ROW_NUMBER() OVER ( PARTITION BY [course] ORDER BY [point] DESC ) AS RowNumber
FROM [dbo].[Points]) AS X
WHERE X.RowNumber<=2
這個主題就討論到此,有交流或者有更好實現方法的同學一定@我額。