新聞中心
下面通過具體的方案將用來討論和演示不同的函數(shù)和它們的子句。

石獅網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,石獅網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為石獅數(shù)千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個(gè)售后服務(wù)好的石獅做網(wǎng)站的公司定做!
十一位演講者在會議中發(fā)表演講,并且為他們的講話獲得范圍為 1 到 9 的分?jǐn)?shù)。結(jié)果被總結(jié)并存儲在下面的 SpeakerStats 表中:
Code |
每個(gè)演講者都在該表中具有一個(gè)行,其中含有該演講者的名字、議題、平均得分、填寫評價(jià)的與會者相對于參加會議的與會者數(shù)量的百分比以及該演講者發(fā)表演講的次數(shù)。本節(jié)演示如何使用新的排序函數(shù)分析演講者統(tǒng)計(jì)數(shù)據(jù)以生成有用的信息。
1、ROW_NUMBER()函數(shù)
返回結(jié)果集分區(qū)內(nèi)行的序列號,每個(gè)分區(qū)的第一行從 1 開始。一般與OVER連用。
例如,假設(shè)您要返回所有演講者的 speaker、track 和 score,同時(shí)按照 score 降序向結(jié)果行分配從 1 開始的連續(xù)值。以下查詢通過使用 ROW_NUMBER 函數(shù)并指定 OVER (ORDER BY score DESC) 生成所需的結(jié)果:
Code |
得分最高的演講者獲得行號 1,得分最低的演講者獲得行號 11。ROW_NUMBER 總是按照請求的排序?yàn)椴煌男猩刹煌男刑?。請注意,如果?OVER() 選項(xiàng)中指定的 ORDER BY 列表不唯一,則結(jié)果是不確定的。這意味著該查詢具有一個(gè)以上正確的結(jié)果;在該查詢的不同調(diào)用中,可能獲得不同的結(jié)果。例如,在我們的示例中,有三個(gè)不同的演講者獲得相同的最高得分 (9):Jessica、Ron 和 Suzanne。由于 SQL Server 必須為不同的演講者分配不同的行號,因此您應(yīng)當(dāng)假設(shè)分別分配給 Jessica、Ron 和 Suzanne 的值 1、2 和 3 是按任意順序分配給這些演講者的。如果值 1、2 和 3 被分別分配給 Ron、Suzanne 和 Jessica,則結(jié)果應(yīng)該同樣正確。
如果您指定一個(gè)唯一的 ORDER BY 列表,則結(jié)果總是確定的。例如,假設(shè)在演講者之間出現(xiàn)得分相同的情況時(shí),您希望使用最高的 pctfilledevals 值來分出先后。如果值仍然相同,則使用最高的 numsessions 值來分出先后。最后,如果值仍然相同,則使用最低詞典順序 speaker 名字來分出先后。由于 ORDER BY 列表 — score、pctfilledevals、numsessions 和 speaker — 是唯一的,因此結(jié)果是確定的:
Code
SELECT ROW_NUMBER() OVER(ORDER BY score DESC, pctfilledevals DESC, numsessions DESC, speaker) AS rownum, speaker, track, score, pctfilledevals, numsessions
FROM SpeakerStatsrownum speaker trackscore pctfilledevals numsessions
------ ---------- ---------- ----------- -------------- -----------
1 Ron Dev 9 30 3
2 Suzanne DB 9 30 3
3 JessicaDev 9 19 1
4 Michele Sys 8 31 4
5 Kathy Sys 8 27 2
6 Mike DB 8 20 3
7 Kevin DB 7 25 4
8 Brian Sys 7 22 3
9 RobertDev 6 28 2
10 Joe Dev 6 20 2
11 Dan Sys 3 22 4
本節(jié)所講到排序函數(shù)的重要好處之一是它們的效率。SQL Server 的優(yōu)化程序只需要掃描數(shù)據(jù)一次,以便計(jì)算值。它完成該工作的方法是:使用在排序列上放置的索引的有序掃描,或者,如果未創(chuàng)建適當(dāng)?shù)乃饕?,則掃描數(shù)據(jù)一次并對其進(jìn)行排序。
另一個(gè)好處是語法的簡單性。為了讓您感受一下通過使用在 SQL Server 的較低版本中采用的基于集的方法來計(jì)算排序值是多么困難和低效,請考慮下面的 SQL Server 2000 查詢,它返回與上一個(gè)查詢相同的結(jié)果:
Code |
該查詢顯然比 SQL Server 2005 查詢復(fù)雜得多。此外,對于 SpeakerStats 表中的每個(gè)基礎(chǔ)行,SQL Server 都必須掃描該表的另一個(gè)實(shí)例中的所有匹配行。對于基礎(chǔ)表中的每個(gè)行,平均大約需要掃描該表的一半(最少)行。SQL Server 2005 查詢的性能惡化是線性的,而 SQL Server 2000 查詢的性能惡化是指數(shù)性的。即使是在相當(dāng)小的表中,性能差異也是顯著的。
行號的一個(gè)典型應(yīng)用是通過查詢結(jié)果分頁。給定頁大?。ㄒ孕袛?shù)為單位)和頁號,需要返回屬于給定頁的行。例如,假設(shè)您希望按照“score DESC, speaker”順序從 SpeakerStats 表中返回第二頁的行,并且假定頁大小為三行。下面的查詢首先按照指定的排序計(jì)算派生表 D 中的行數(shù),然后只篩選行號為 4 到 6 的行(它們屬于第二頁):
Code |
以下為結(jié)果集:
rownum speaker trackscore |
用更一般的術(shù)語表達(dá)就是,給定 @pagenum 變量中的頁號和 @pagesize 變量中的頁大小,以下查詢返回屬于預(yù)期頁的行:
Code |
上述方法對于您只對行的一個(gè)特定頁感興趣的特定請求而言已經(jīng)足夠了。但是,當(dāng)用戶發(fā)出多個(gè)請求時(shí),該方法就不能滿足需要了,因?yàn)樵摬樵兊拿總€(gè)調(diào)用都需要您對表進(jìn)行完整掃描,以便計(jì)算行號。當(dāng)用戶可能反復(fù)請求不同的頁時(shí),為了更有效地進(jìn)行分頁,請首先用所有基礎(chǔ)表行(包括計(jì)算得到的行號)填充一個(gè)臨時(shí)表,并且對包含這些行號的列進(jìn)行索引:
|
然后,對于所請求的每個(gè)頁,發(fā)出以下查詢:
DECLARE @pagenum AS INT, @pagesize AS INT |
只有屬于預(yù)期頁的行才會被掃描。
分段
可以在行組內(nèi)部獨(dú)立地計(jì)算排序值,而不是為作為一個(gè)組的所有表行計(jì)算排序值。為此,請使用 PARTITION BY 子句,并且指定一個(gè)表達(dá)式列表,以標(biāo)識應(yīng)該為其獨(dú)立計(jì)算排序值的行組。例如,以下查詢按照“score DESC, speaker”順序單獨(dú)分配每個(gè) track 內(nèi)部的行號:
Code |
以下為結(jié)果集:
trackpos speaker score |
在 PARTITION BY 子句中指定 track 列會使得為具有相同 track 的每個(gè)行組單獨(dú)計(jì)算行號。
#p#
2、RANK, DENSE_RANK
RANK 和 DENSE_RANK 函數(shù)非常類似于 ROW_NUMBER 函數(shù),因?yàn)樗鼈円舶凑罩付ǖ呐判蛱峁┡判蛑?,而且可以根?jù)需要在行組(分段)內(nèi)部提供。但是,與 ROW_NUMBER 不同的是,RANK 和 DENSE_RANK 向在排序列中具有相同值的行分配相同的排序。當(dāng) ORDER BY 列表不唯一,并且您不希望為在 ORDER BY 列表中具有相同值的行分配不同的排序時(shí),RANK 和 DENSE_RANK 很有用。RANK 和 DENSE_RANK 的用途以及兩者之間的差異可以用示例進(jìn)行最好的解釋。以下查詢按照 score DESC 順序計(jì)算不同演講者的行號、排序和緊密排序值:
Code
SELECT speaker, track, score,
ROW_NUMBER() OVER(ORDER BY score DESC) AS rownum,
RANK() OVER(ORDER BY score DESC) AS rnk,
DENSE_RANK() OVER(ORDER BY score DESC) AS drnk
FROM SpeakerStatsspeaker trackscore rownum rnk drnk
---------- ---------- ----------- ------ --- ----
Jessica Dev 9 1 1 1
Ron Dev 9 21 1
Suzanne DB 9 31 1
KathySys 8 44 2
Michele Sys 854 2
Mike DB 864 2
KevinDB 777 3
BrianSys 787 3
Joe Dev 699 4
Robert Dev 6 10 9 4
Dan Sys 311 11 5
正如前面討論的那樣,score 列不唯一,因此不同的演講者可能具有相同的得分。行號確實(shí)代表下降的 score 順序,但是具有相同得分的演講者仍然獲得不同的行號。但是請注意,在結(jié)果中,所有具有相同得分的演講者都獲得相同的排序和緊密排序值。換句話說,當(dāng) ORDER BY 列表不唯一時(shí),ROW_NUMBER 是不確定的,而 RANK 和 DENSE_RANK 總是確定的。排序值和緊密排序值之間的差異在于,排序代表:具有較高得分的行號加 1,而緊密排序代表:具有明顯較高得分的行號加 1。從您迄今為止已經(jīng)了解的內(nèi)容中,您可以推導(dǎo)出當(dāng) ORDER BY 列表唯一時(shí),ROW_NUMBER、RANK 和 DENSE_RANK 產(chǎn)生完全相同的值。
3、NTILE
NTILE 使您可以按照指定的順序,將查詢的結(jié)果行分散到指定數(shù)量的組 (tile) 中。每個(gè)行組都獲得不同的號碼:第一組為 1,第二組為 2,等等。您可以在函數(shù)名稱后面的括號中指定所請求的組號,在 OVER 選項(xiàng)的 ORDER BY 子句中指定所請求的排序。組中的行數(shù)被計(jì)算為 total_num_rows / num_groups。如果有余數(shù) n,則前面 n 個(gè)組獲得一個(gè)附加行。因此,可能不會所有組都獲得相等數(shù)量的行,但是組大小最大只可能相差一行。例如,以下查詢按照 score 降序?qū)⑷齻€(gè)組號分配給不同的 speaker 行:
Code |
以下為結(jié)果集:
speaker trackscore rownum tile |
在 SpeakerStats 表中有 11 位演講者。將 11 除以 3 得到組大小 3 和余數(shù) 2,這意味著前面 2 個(gè)組將獲得一個(gè)附加行(每個(gè)組中有 4 行),而第三個(gè)組則不會得到附加行(該組中有 3 行)。組號(tile 號)1 被分配給行 1 到 4,組號 2 被分配給行 5 到 8,組號 3 被分配給行 9 到 11。通過該信息可以生成直方圖,并且將項(xiàng)目均勻分布到每個(gè)梯級。在我們的示例中,第一個(gè)梯級表示具有最高得分的演講者,第二個(gè)梯級表示具有中等得分的演講者,第三個(gè)梯級表示具有最低得分的演講者??梢允褂?CASE 表達(dá)式為組號提供說明性的有意義的備選含義:
Code |
以下為結(jié)果集:
speaker trackscore scorecategory |
標(biāo)題名稱:詳解SQLServer2005四種排名函數(shù)
文章地址:http://www.5511xx.com/article/ccchosj.html


咨詢
建站咨詢
