SQL Server排名函數與排名開窗函數


什么是排名函數?說實話我也不甚清楚,我知道 order by 是排序用的,那么什么又是排名函數呢?

接下來看幾個示例就明白了。

首先建立一個表,隨便插入一些數據。

ROW_NUMBER 函數:直接排序,ROW_NUMBER函數是以上升進行直接排序,並且以連續的順序給每一行數據一個唯一的序號。(即排名連續)

1 -- 以下是根據 U_Pwd 這一列進行排名(升序)
2 select *,
3 ''+convert(varchar,ROW_NUMBER() over(order by U_Pwd))+'' RowNum
4 from UserInfo

RANK 函數:並列排序,在 order by 子句中指定的列,如果返回一行數據與另一行具有相同的值,rank函數將給這些行賦予相同的排名數值。

在排名的過程中,保持一個內部計數值,當值有所改變時,排名序號將有一個跳躍。(即排名不連續)

1 -- 以下是根據 U_Pwd 這一列進行排名(升序)
2 select *,
3 ''+convert(varchar,rank() over(order by U_Pwd))+'' RowNum
4 from UserInfo

可以明確的看到有4行數據並列第2名,然后直接就是第6名,這是因為 order by 子句中指定的列 U_Pwd 的值相同。

DENSE_RANK 函數:並列排序,這一點與 RANK() 函數類似,order by 子句指定的列的值相同,排名數值相同,但是后面是連續的。(即排名連續)

1 -- 以下是根據 U_Pwd 這一列進行排名(升序)
2 select *,
3 ''+convert(varchar,DENSE_RANK() over(order by U_Pwd))+'' RowNum
4 from UserInfo

可以看到即使有4行數據並列第2名,但是接下來依然是第3名。

NTILE 函數:將查詢的結果分發到指定數量的組中。 各個組有編號,編號從1開始。 對於每一行,NTILE 將返回此行所屬的組的編號。

組中的行數計算方式為 total_num_rows(結果集的總行數) / num_groups(指定的組數)。

如果有余數 n,則前面 n 個組獲得一個附加行。因此,可能不會所有組都獲得相等數量的行,但是組大小最大只可能相差一行。

例如,如果總行數是 53,組數是 5,53 / 5 等於10余數是3,按上面個規則就是,每組分配10行,又因余數為3,所以前面3組每組附加一行。

則前三個組每組包含 11 行,其余兩個組每組包含 10 行。

另一方面,如果總行數可被組數整除,則行數將在組之間平均分布。 例如,如果總行數為 50,有五個組,則每組將包含 10 行。

1 -- 以下是根據 U_Pwd 這一列進行分組
2 select *,
3 ''+convert(varchar,NTILE(3) over(order by U_Pwd))+'' RowNum
4 from UserInfo

這個表中有10條數據,指定分為3組,10/3等於3余數1。

PS:排名函數后面必須有 over() 子句。

 

排名開窗函數:

ROW_NUMBER、DENSE_RANK、RANK、NTILE屬於排名函數,OVER()就是窗口函數。

窗口函數OVER()指定一組行,開窗函數計算從窗口函數輸出的結果集中各行的值。

開窗函數不需要使用GROUP BY就可以對數據進行分組,還可以同時返回基礎行的列和聚合列。

排名開窗函數可以單獨使用ORDER BY 語句,也可以和PARTITION BY同時使用。

ODER BY 指定排名開窗函數的順序。在排名開窗函數中必須使用ORDER BY語句。

PARTITION BY用於將結果集進行分組,開窗函數應用於每一組。

1 -- 以下是先根據 U_Pwd 這一列進行分組,然后每一組再根據 U_Pwd 排序
2 select *,
3 ''+convert(varchar,ROW_NUMBER() over(partition by U_Pwd order by U_Pwd))+'' RowNum
4 from UserInfo

因為 U_Pwd 這一列有4種不同的值,所以分為4組,然后 ROW_NUMBER 再在每一組中進行連續排序。

 

1 -- 以下是先根據 U_Pwd 這一列進行分組,然后每一組再根據 U_Pwd 排序
2 select *,
3 ''+convert(varchar,rank() over(partition by U_Pwd order by U_Pwd))+'' RowNum
4 from UserInfo

因為 U_Pwd 這一列有4種不同的值,所以同樣是分為4組,然后 RANK 再在每一組中進行排序,因為RANK是並列排序,所以全部都是第一名。下面換個字段排序試試看。

1 -- 以下是先根據 U_Pwd 這一列進行分組,然后每一組再根據 U_Name 排序
2 select *,
3 ''+convert(varchar,rank() over(partition by U_Pwd order by U_Name))+'' RowNum
4 from UserInfo

 

1 -- 以下是先根據 U_Pwd 這一列進行分組,然后每一組再根據 U_Pwd 排序
2 select *,
3 ''+convert(varchar,DENSE_RANK() over(partition by U_Pwd order by U_Pwd))+'' RowNum
4 from UserInfo

因為 U_Pwd 這一列有4種不同的值,所以同樣是分為4組,然后 DENSE_RANK 再在每一組中進行排序,因為DENSE_RANK也是並列排序,所以全部都是第一名。下面換個字段排序試試看。

1 -- 以下是先根據 U_Pwd 這一列進行分組,然后每一組再根據 U_Name 排序
2 select *,
3 ''+convert(varchar,DENSE_RANK() over(partition by U_Pwd order by U_Name))+'' RowNum
4 from UserInfo

 

1 -- 以下是先根據 U_Pwd 這一列進行分組,然后每一組再根據 NTILE(3) 指定的組數分組,最后在根據 order by 子句指定的字段 U_Pwd 排序 
2 select *,
3 ''+convert(varchar,NTILE(3) over(partition by U_Pwd order by U_Pwd))+'' RowNum
4 from UserInfo

因為 U_Pwd 這一列有4種不同的值,所以同樣是分為4組。第1組有1條數據,所以就1個區。第2組有4條數據,4/3等於1余數1,所以第2組分為3個區,又因余數為1,所以第1個區附加1行。第3組有3條數據,3/3等於1余數為0,所以第3組有3個區。第4組有2條數據,所以分為2個區。

PS:在排序開窗函數中使用 PARTITION BY 子句需要放置在 ORDER BY子句之前。

 

參考:

http://www.cnblogs.com/jhxk/articles/2531595.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM