2010-02-17 123 views
1

我正在編寫一個web應用程序,它應該在搜索查詢中顯示非常大的結果。 說一些查詢將返回10.000項。 我想將這些顯示給用戶分頁;到目前爲止沒有問題:每個頁面將是帶有適當的LIMIT語句的查詢的結果。 但我想在分頁查詢的每個頁面中顯示結果的線索:來自第一個項目的一些數據和來自最後一個的一些數據。 這意味着,例如,與10.000項目的結果和50項的頁面大小,如果用戶要求的第一頁,我將需要:sql查詢得到一個不連續的結果子集

  • 第50項(被請求的頁面用戶)
  • 項目51和100(第一和最後的第二頁的)
  • 項目101和151

對於我想避免一個查詢磷效率的原因呃排。

[編輯]我也寧願不下載10.000的結果,如果我只需要50 +五十零分之萬* 2 = 400

的問題是:是否有一個查詢我可以發出到RDBMS(MySQL的,順便說一下,但我更喜歡cross-db解決方案),它只會返回我需要的數據?

我不能使用服務器端遊標,因爲並不是所有的dbs都支持它,我希望我的應用程序可以與數據庫無關。

回答

0

更新:我完全誤讀了最初的問題。您可以在MySQL中使用UNIONLIMIT子句來完成此操作,但它可能是您「每行一個查詢」的含義。語法如下:

select FOO from BAZ limit 50 
    union 
select FOO from BAZ limit 50, 1 
    union 
select FOO from BAZ limit 99, 1 
    union 
select FOO from BAZ limit 100, 1 
    union 
select FOO from BAZ limit 149, 1 

等等等等。由於您使用的是UNION,因此您只需要一次往返數據庫。不過,我不確定MySQL如何處理各種SELECT聲明。它應該能夠認識到他們在本質上是相同的查詢和使用緩存的查詢計劃,但我不使用MySQL足夠的工作,知道這是一個以優化的合理預期。

顯然,要以通用方式構建此查詢,首先需要運行count查詢,以便計算偏移量。

這肯定不是標準的SQL易處理的問題,因爲分頁邏輯需要非標準的功能。

+1

對不起,誤解你的問題(早晨咖啡還在醞釀之中)。我會調整我的答案。 – 2010-02-17 11:36:34

+1

好點:這將最大限度地減少對使用的數據庫的依賴:只有限制語法將不得不進行調整。 分頁邏輯需要非標準功能。每當我偶然發現這一點,我真的很驚訝:這樣一個基本的構造怎麼能不被標準化呢? – silviot 2010-02-17 13:20:41

+0

這裏的問題是查詢不能被參數化。如果我想要100頁的話呢?或者如果我想要第100頁以及上一頁和下一頁?然後你必須立即創建SQL。 – 2010-02-17 13:25:39

2

只是爲了好玩,這裏是它的MSSQL版本。

declare @pageSize as int; set @pageSize = 10; 
declare @pageIndex as int; set @pageIndex = 0; /* first page */ 
WITH x AS 
( 
    select 
     ROW_NUMBER() OVER (ORDER BY (created) ASC) AS RowNumber, 
     * 
    from table 
) 
SELECT * FROM x 
WHERE 
    ((RowNumber <= (@pageIndex+1)*@pageSize) AND (RowNumber >= @pageIndex*@PageSize+1)) 
    OR 
    RowNumber % @pageSize = 1 
    OR 
    RowNumber % @pageSize = @pageSize-1 

請注意,在over子句中提供了ORDER BY。
另外請注意,如果你有gazillion行,你的結果集將有數百萬。出於實際原因,您需要最大化結果行。

我不知道如何在通用SQL中解決這個問題。 (我打賭:。沒辦法,即使簡單的pageing離不開特定的DB-運營商來解決)

+0

與Hank Gay提供的(簡單的)相比,我應該調查此解決方案的效率。謝謝。 – silviot 2010-02-17 13:22:07