如果一個(gè)查詢的結(jié)果數(shù)據(jù)量巨大,就需要數(shù)據(jù)查詢的時(shí)候就分頁(yè),每次只返回其中一頁(yè)
第一種方法:
思路是根據(jù)頁(yè)號(hào)取出兩部分?jǐn)?shù)據(jù),比如取出前90條,然后取出前100條,然后比較取出兩次結(jié)果的差集。
在30萬(wàn)條記錄的情況下,如果只分100頁(yè)(結(jié)果有10000條記錄),大約需要1分半鐘。索引建得好的話,1分鐘左右。
//select * from //這一句是不能修改的了,因?yàn)樗菑慕Y(jié)果中讀取,所以必須要用*
//(select top @h_count (@filedlist) from @tableName .....) as big //取出符合條件的上限的記錄
//where
//big.guid //這里是關(guān)鍵,根據(jù)主鍵從下限結(jié)果中過(guò)濾掉重復(fù)的記錄(只留下不同的數(shù)據(jù),也就是求交集)
//not in
//(select top @l_count guid from @table .....)//下限
//order @orderby //原來(lái)的格式,這里只保留了orderby之后的,應(yīng)該保留條件之后所有的,包括gruopby什么的
函數(shù)類似如此:
public string MakeSqlPager(string sourceSql,int pageIndex)
{
//使用默認(rèn)頁(yè)面大小
string orderbyStr=sourceSql.Substring(sourceSql.ToLower().IndexOf("order by"));
int index=sourceSql.ToLower().IndexOf("select");
string bigRes="("+ sourceSql.Insert(index+6," top "+((pageIndex+1)*_pageSize).ToString()+" ")+") as big";
string smallRes="("+ sourceSql.Insert(index+6," top "+(pageIndex*_pageSize).ToString()+" ")+")";
return "select * from "+bigRes+" where big.guid not in "+smallRes+" "+orderbyStr;
}
這種方法還可以改進(jìn),就是第二次取過(guò)濾時(shí)從第一個(gè)的結(jié)果里面過(guò)濾。
第二種方法:
掐頭去尾,程序還沒(méi)寫(xiě)
SELECT * FROM
(
SELECT TOP 100 * FROM
(
SELECT TOP 100000 * FROM pagetest ORDER BY regt ASC
) as a
ORDER BY regt desc
) as b
ORDER BY regt ASC
測(cè)試了一下,大約用時(shí)間29秒。
比較:
第一種方法的效率很低,猜測(cè)是因?yàn)槎啻涡枰h(huán)比較,時(shí)間復(fù)雜度要高一個(gè)等級(jí)。比如,這種方法的響應(yīng)時(shí)間和所取得的頁(yè)號(hào)有很大關(guān)系。
第二種方法還是可以接受的,和頁(yè)號(hào)無(wú)關(guān),但是也需要兩次比較
網(wǎng)上還有使用比較ID的方法的,但是不是所有的表都有ID,即使有,也不一定是int類型的。
還有用存儲(chǔ)過(guò)程創(chuàng)建臨時(shí)表的,我還沒(méi)有測(cè)試效率如何
sqlserver里面沒(méi)有rownum 這個(gè)功能(最新的2005beta2版本據(jù)說(shuō)有了,Oracle里面有),所以一次比較就能分頁(yè)的算法還真不好寫(xiě)