sql decimal函数例子_leetcode题库-sql练习精讲系列--三、经典排名问题
這是一個系列文章,這個系列的理念是通過一道題,搞懂一類題。涵蓋了SQL面試最常考的知識點。搞懂這些題,面試時工作中sql不可能有問題。
文章分為引入問題-完整解析-答案-leetcode題和答案-知識點拓展-BAT等大廠面試真題幾個部分。
希望能幫你全方位的弄懂。有問題可以留言,碼字不易,寫一篇要好幾個小時,希望能得到點贊收藏哦。
一、問題
下圖是"01課程成績"表中的內容,記錄了每個學生學生編號,課程編號和成績。
現在需要根據成績來排名,如果兩個分數相同,那么排名要是并列的。
比如題目中的成績從大到小排序應該是80,80,76,70,50,31。分數相同排名并列,那么6位同學的排序應該是1,1,3,4,5,6。
二、數據準備
create table 成績 (`學生編號` varchar(10), `課程編號` varchar(10), `成績` decimal(18,1));insert into `成績` values('01' , '01' , 80); insert into `成績` values('02' , '01' , 70); insert into `成績` values('03' , '01' , 80); insert into `成績` values('04' , '01' , 50); insert into `成績` values('05' , '01' , 76); insert into `成績` values('06' , '01' , 31);【解答】
[解題思路]
從上面的結果圖中的紅色框可以看出:
- rank():跳躍排序;同分并列,但會占用下一個排名名額。
- dense_rank():連續(xù)排序;單詞直譯為密集排序。同分并列,不占用下一個排名名額。
- row_number():沒有重復值的排序(記錄相等也是不重復的),可以進行分頁使用。
3.根據題目中要求的分數相同,排名并列,且占用下一個名額。所以我們使用rank()函數。
[代碼]
select *,rank() over (order by 成績 desc) as `rank` from 成績[leetcode題庫問題-178. 分數排名]
編寫一個 SQL 查詢來實現分數排名。
如果兩個分數相同,則兩個分數排名(Rank)相同。請注意,平分后的下一個名次應該是下一個連續(xù)的整數值。換句話說,名次之間不應該有“間隔”。
例如,根據上述給定的 Scores 表,你的查詢應該返回(按分數從高到低排列):
[參考答案]
select score, dense_rank() over(order by Score desc) as Ranking from Scores;[知識點講解]
[窗口函數是什么]
窗口的概念非常重要,它可以理解為記錄集合,或者理解為分區(qū)。窗口函數也就是在滿足某種條件的記錄集合上執(zhí)行的特殊函數。對于每條記錄都要在此窗口內執(zhí)行函數,有的函數隨著記錄不同,窗口大小都是固定的,這種屬于靜態(tài)窗口;有的函數則相反,不同的記錄對應著不同的窗口,這種動態(tài)變化的窗口叫滑動窗口。
窗口函數和普通聚合函數也很容易混淆,二者區(qū)別如下:
- 聚合函數是將多條記錄聚合為一條;而窗口函數是每條記錄都會執(zhí)行,有幾條記錄執(zhí)行完還是幾條。
- 聚合函數也可以用于窗口函數中。
[窗口函數語法]
函數名([expr]) over 子句 :
over是關鍵字,用來指定函數執(zhí)行的窗口范圍,如果后面括號中什么都不寫,則意味著窗口包含滿足where條件的所有行,窗口函數基于所有行進行計算;如果不為空,則支持以下四種語法來設置窗口:
?```sql select * from( select row_number()over w as row_num,order_id,user_no,amount,create_datefrom order_tabWINDOW w AS (partition by user_no order by amount desc))t ; ?```- window_name:給窗口指定一個別名,如果SQL中涉及的窗口較多,采用別名可以看起來更清晰易讀。上面例子中如果指定一個別名w,則改寫如下:
- partition子句:窗口按照那些字段進行分組,窗口函數在不同的分組上分別執(zhí)行。上面的例子就按照用戶id進行了分組。在每個用戶id上,按照order by的順序分別生成從1開始的順序編號。
- order by子句:按照哪些字段進行排序,窗口函數將按照排序后的記錄順序進行編號。可以和partition子句配合使用,也可以單獨使用。上例中二者同時使用,如果沒有partition子句,則會按照所有用戶的訂單金額排序來生成序號。
- frame子句:frame是當前分區(qū)的一個子集,子句用來定義子集的規(guī)則,通常用來作為滑動窗口使用。比如要根據每個訂單動態(tài)計算包括本訂單和按時間順序前后兩個訂單的平均訂單金額,則可以設置如下frame子句來創(chuàng)建滑動窗口:
[窗口函數匯總]
- CUME_DIST(): 函數計算一組值中的值的累積分布。
- LAG(): 對當前行之前的指定物理偏移量的行的訪問。
- LEAD(): 對當前行之后的指定物理偏移量的行的訪問。
- NTILE(): 有序分區(qū)的行分配到指定數量的大致相等的組或桶中。
- PERCENT_RANK(): 函數計算結果集的分區(qū)中值的相對位置。
- DENSE_RANK()
- RANK()
- ROW_NUMBER()
四、大廠面試真題
[支付寶面試真題] 找出支付金額在累計前20%的用戶
現有交易數據表user_sales_table如下:
user_name 用戶名
pay_amount 用戶支付額度
找出支付金額在累計前20%的用戶。
輸出要求如下:
user_name 用戶名(前20%的用戶)
/* ntile(5) over(order by sum(pay_amount) desc) as level 按照支付金額累計倒序排列后分成大致相同的5組。 */select b.user_name from(selectuser_name,ntile(5) over(order by sum(pay_amount) desc) as level -- 分成5組from user_sales_table group by user_name ) bwhere b.level = 1總結
以上是生活随笔為你收集整理的sql decimal函数例子_leetcode题库-sql练习精讲系列--三、经典排名问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: byte 类型比较_C++数据类型回顾
- 下一篇: 乌班图配置mysql Java_Ubun