最近項目中需要在SQL SERVER中進行分頁,需要編寫分頁查詢語句。之前也寫過一些關于分頁查詢的語句,但是性能不敢恭維。于是在業務時間,在微軟社區Bing了一篇老外寫的關于SQL SERVER分頁的文章。看過之后,感覺自己之前寫的語句,太低端,太不科學了。 文章中講了兩種分頁方法,其中一種只適用于SQL SERVER2012以上版本。
ROW_NUMBER()函數分頁
先介紹一下ROW_NUMBER()函數,這個函數的主要作用,從它的命名中就可看出來。ROW,每列,NUMBER數字,它的作用就是為每行分配一個數字。但是它一般不單獨使用。它的語法是這樣的:
PARTITION BY value_exPRession: 這個參數是通過value_expression,把我們查詢到結果集給分成若干區。舉個例子,我們有一張成績表。我們要為女生、男生在各自性別內按成績排名次。這時,我們就可以通過PARTITTION BY GENDER(性別字段) 將全班人員分為兩個區,女生區、男生區。男生在男生區排名次,女生在女生區排名次。
order_by_clause:這個是就是order by 語句,將數據集按某個字段進行排序。
需要注意的是,PARTITION BY value_expression不是必要參數,但是order_by_clause是必要參數。要使用ROW_NUMBER()必須要有order by 語句。下面給出幾個ROW_NUMBER() 實際使用場景:
1.
這個語句把表中TerritoryName不為空、SalesYID不為空的數據按字段SalesYTD降序排序,再通過ROW_NUMBER()函數為每行分配一個連續的數字,將數字存入新添加的一個名為Row的字段中。結果如下:
2.這種情況,就是我們今天要講的分頁方法。(Returning a subset of rows)
在這個場景中,我們用到了Comoon table expression(中間表表達式),它的作用與臨時表差不多。就是將查詢到的結果放入一個地方,供再次查詢。對Common Table Expression感興趣的可以去MSDN上學習。原文地址:http://msdn.microsoft.com/en-us/library/ms175972.aspx.
我們使用ROW_NUMBER()函數為查詢的結果每行數據分配一個數字,將數字放入RowNumber列中(通過AS 生成的新列)。再將數據集放入中間表OrderedOrders中。查詢中間表,這個時候我們就可以使用Where RowNumber BETWEEN A AND B.來讀取從A條到B條的數據了,就可以達到我們的分頁需求了.
3.Using ROW_NUMBER() with PARTITION
在這個場景中,我們用到了PARTITION參數。我們按區域(territoryName)將查詢結果進行分區,再在分過區的數據集中以SalesYTD降序,再為降序后的每行數據分配數字。最后以TerritoryName字段升序。結果如下圖:
關于ROW_NUMBER()的原文地址:http://msdn.microsoft.com/en-us/library/ms186734.aspx.
這種分頁方法的主要思想,就是通過ROW_NUMBER()為每行生成標識。再通過BETWEEN AND 語句來獲取當前頁的數據,已達到分頁的作用。
我們創建了一個表名TB.EXMPLE的表,添加了1,000,000條數據。我們通過這種分頁方法來編寫如下查詢語句:
-----查看每頁顯示10條,第2頁的數據 DECLARE @PageNumber AS INT,@RowNumber AS INTSET @PageNumber=2SET @RowNumber=5SELETCT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY ID_EXMPLE) AS NUMBER, * FROM TB_EXAMPLE )AS TBLWHERE NUMBER BETWEEN ((@PageNumber-1)*@RowNumber+1) AND (@PageNumber*@RowNumber)
結果如下:
2.OFFSET AND FETCH 分頁
offset and fetch,這是SQL SERVER 2012新添加的功能。2012以下版本,不支持。
DECALER @PageNumber AS INT,@RowNumber AS INTSET @PageNumber=2SET @RowNumber=5SELECT * FROM TB_EXAMPLEWHERE OFFSET ((@PageNumber-1)*@RowNumber) ROWSFETCH NEXT @RowNumber ROWS ONLY;
OFFSET A ROWS ,將前A條記錄舍去,FETCH NEXT B ROWS ,向后在讀取B條數據。
原文地址如下:http://social.technet.microsoft.com/wiki/contents/articles/23811.paging-a-query-with-sql-server.aspx.
新聞熱點
疑難解答