1. 程式人生 > >SQL 高效分頁(百萬條資料)ROW_NUMBER() OVER (ORDER BY id) | 分頁

SQL 高效分頁(百萬條資料)ROW_NUMBER() OVER (ORDER BY id) | 分頁


第一種方法:效率最高

SELECT TOP 頁大小 * 
FROM 
	(
	    SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNumber,* FROM table1
	)   as A  
WHERE RowNumber > 頁大小*(當前頁-1) 

--註解:首先利用Row_number()為table1表的每一行新增一個行號,給行號這一列取名'RowNumber' 在over()方法中將'RowNumber'做了升序排列
--然後將'RowNumber'列 與table1表的所有列 形成一個表A
--重點在where條件。假如當前頁(currentPage)是第2頁,每頁顯示10個數據(pageSzie)。那麼第一頁的資料就是第11-20條
--所以為了顯示第二頁的資料,即顯示第11-20條資料,那麼就讓RowNumber大於 10*(2-1) 即:頁大小*(當前頁-1)

將上面的方法寫成儲存過程 (表名Location)

if(exists(select* from sys.procedures where name='p_location_paging'))--如果p_location_paging這個儲存過程存在
drop proc p_location_paging  --那麼就刪除這個儲存過程
go
create proc p_location_paging(@pageSize int, @currentPage int)--建立儲存過程,定義兩個變數'每頁顯示的條數'和'當前頁'
as
select  top (@pageSize) * from (
select ROW_NUMBER() over(order by locid) as rowid ,* from location 
)as A
where rowid> (@pageSize)*((@currentPage)-1)

簡單的說row_number()從1開始,為每一條分組記錄返回一個數字


第二種方法:效率次之

SELECT TOP 頁大小 *  --如果每頁顯示10條資料,那麼這裡就是查詢10條資料
FROM table1
WHERE id >  --假如當前頁為第三頁,那麼就需要查詢21-30條資料,即:id>20
        (
            SELECT ISNULL(MAX(id),0)  --查詢子查詢中最大的id
            FROM 
                (
					SELECT TOP 頁大小*(當前頁-1) id FROM table1 ORDER BY id --因為當前頁是第三頁,每頁顯示十條資料。那麼我將: 頁大小*(當前頁-1),就是獲取到了在"當前頁""前面"的20條資料。所以上面用max(id)查詢最大的id,取到這個20,那麼前面的where 條件的id>20 即取到了第三頁的資料,即取21-30條資料
                ) as A
           )
ORDER BY id

將上面的方法寫成儲存過程:表名Location
if(exists(select * from sys.procedures where name='p_location_paging'))
drop proc p_location_paging
go
create proc p_location_paging(@pageSize int ,@currentPage int)
as
select  top (@pageSize) * from location
where locId>(select ISNULL(MAX(locId),0)
from (select top ((@pageSize)*(@currentPage-1))locid from location  order by locId) as a
)
order by locId

第三種方法:效果最差

SELECT TOP 頁大小 *
FROM table1
WHERE id NOT IN --where條件語句限定要查詢的資料不是子查詢裡面包含的資料。即查詢"子查詢"後面的10條資料。即當前頁的資料
        (
		   --如果當前頁是第二頁,每頁顯示10條資料,那麼這裡就是獲取當前頁前面的所有資料。
           SELECT TOP 頁大小*(當前頁-1) id FROM table1 ORDER BY id
        )
ORDER BY id

在知道總的資料量,及每頁顯示多少條資料後。計算總的頁數

<1> 即便資料總的條數為0。也顯示一頁; 即:總頁數=1

int dataCount; //資料的總的條數
int pageSize;  //每頁顯示多少條資料
int pageCount; //總的頁數
pageCount = dataCount % pageSize == 0 ? ((dataCount - pageSize >= 0 ? (dataCount / pageSize) : 1)) : dataCount / pageSize + 1;

//上面這句話分解一下就是:
if(dataCount%pageSize==0) 
{
	if(dataCount-pageSize>=0) //即if(dataCount>pageSize)
	{
		pageCount=dataCount/pageSize;
	}
	else
	{
		pageCount=1; //假如資料的總條數只有8條資料。而每頁顯示10條資料;也就是說8%10的結果是等於0的。但是既然有8條資料,我也需要用1頁來顯示這8條資料。所有就有這個條件:即:即便dataCount%pageSize==0的時候,在dataCount<pageSize的情況下,總頁數PageCount最少也得有一頁吧!所以這裡就將pageCount設為1了。
	}

}
else
{
	dataCount=(dataCount/pageSize)+1;
}

<2>如果資料總條數為0。連一頁都不需要顯示;即:總頁數=0

int dataCount; //資料的總的條數
int pageSize;  //每頁顯示多少條資料
int pageCount; //總的頁數
 pageCount = dataCount % pageSize == 0 ? ((dataCount - pageSize >= 0 ? (dataCount / pageSize) : (dataCount==0?0:1))) : dataCount / pageSize + 1;

//上面這句話分解一下就是:
if(dataCount%pageSize==0) 
{
	if(dataCount-pageSize>=0) //即if(dataCount>pageSize)
	{
		pageCount=dataCount/pageSize;
	}
	if(dataCount=0)
	{
		pageCount=0; //相比上面那個計算總頁數,這裡多了這麼一條判斷。如果連一條資料都沒有的情形下,我連一頁都不需要顯示,即:讓總頁數為0,
	}
	else
	{
		pageCount=1; //假如資料的總條數只有8條資料。而每頁顯示10條資料;也就是說8%10的結果是等於0的。但是既然有8條資料,我也需要用1頁來顯示這8條資料。所有就有這個條件:即:即便dataCount%pageSize==0的時候,在dataCount<pageSize的情況下,總頁數PageCount最少也得有一頁吧!所以這裡就將pageCount設為1了。
	}

}
else
{
	dataCount=(dataCount/pageSize)+1;
}