實際項目中需要實現自定義分頁,最關鍵第一步就是寫分頁SQL語句,要求語句效率要高。
那么本文的一個查詢示例是查詢第100000-100050條記錄,即每頁50條的結果集。查詢的表名為infoTab,且id為整型自增主鍵字段。
第一種、使用NOT IN關鍵字
SELECT TOP 50 * FROM infoTab WHERE ID NOT IN(SELECT TOP 100000 ID FROM infoTab)
平均查詢時間0.1s。這是非常簡單的一種寫法,效率還可以,只是使用默認ID排序,如果ID有間斷,展示效果不好。
第二種、通過升序與降序方式實現分頁查詢
SELECT * FROM (SELECT TOP 50 * FROM (SELECT TOP 100050 * FROM infoTab ORDER BY ID ASC)TEMP1 ORDER BY ID DESC)TEMP2 ORDER BY ID ASC
平均查詢時間0.22s。這種是利用先查詢倒序的50個數據,最后又進行升序排序的方法很復雜,不推薦使用,也最浪費時間,效率最低。
第三種、采用MAX(ID)函數
實際是關於MIN()函數和MAX()函數的使用
SELECT TOP 50 * FROM infTab WHERE ID>(SELECT MAX(ID) FROM (SELECT TOP 100000 ID FROM infoTab ORDER BY ID)temp)
平均查詢時間0.13s。這種方法理解起來很簡單,就是直接使用MAX()進行查找,然后id大於MAX()結果為100000的前50條記錄即為結果。
第四種、最后一種推薦使用的方法,使用ROW_NUMBER
正如Oracle的rowid,解決了整型的ID字段不連續的問題。用行號(ROW_NUMBER)查詢,比較高效的查詢方式,只有在SQL Server2005或更高版本才支持。
注意的是,ROW_NUMBER后面必須跟着OVER(ORDER BY [FIELD]),我們來看具體的寫法。
SELECT * FROM (SELECT TOP 100050 ROW_NUMBER() OVER(ORDER BY ID ASC) AS rowid,* FROM infoTab)t WHERE t.rowid > 100000
平均運行時間0.29s。這種方法的好處是實現連續的排序ROWID,避免了ID間斷不連續的問題,展示更加美觀。
在這里面需要注意的是OVER的括號里面可以寫多個排序字段,比如:OVER(ORDER BY CreatedTime, ID)。
如果使用下面這條語句更高效,是上面語句運行時間的三分之一,平均運行時間僅0.08s。
SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY ID ASC) AS rowid,* FROM infoTab)t WHERE t.rowid > 100000 AND t.rowid <= 100050
總之,我們推薦使用第四種方法中的后面一條語句,查詢效率高,而且展示結果美觀,ROWID連續,尤其在千萬級數據查詢的時候,效率相差很大非常大。
(所有SQL語句實測通過,可直接在項目中使用。)