2016-06-24 60 views
1

我有一些我想使用基於遊標的分頁查詢的表,但它需要申請多個列。基於MySQL遊標的多列分頁

讓我們用2列一個簡單的例子 - 我取的第一頁是這樣的:

SELECT column_1, column_2 
FROM table_name 
ORDER BY column_1, column_2 
LIMIT 10 

後,我得到的結果,我可以獲取基於最後一排的下一個頁面。假設最後一行是column_1 = 5, column_2 = 8。我想這樣做:

SELECT column_1, column_2 
FROM table_name 
WHERE column_1 > 5 AND column_2 > 8 
ORDER BY column_1, column_2 
LIMIT 10 

但這顯然是錯誤的。這將篩選出具有column_1 = 5, column_2 = 9(因爲column_1過濾器)的行或具有column_1 = 6, column_2 = 6行(因爲column_2過濾器)

我可以做這樣的事情,以避免該問題:

SELECT column_1, column_2 
FROM table_name 
WHERE column_1 > 5 
OR (column_1 = 5 AND column_2 > 8) 
ORDER BY column_1, column_2 
LIMIT 10 

但這變得非常繁瑣,而且容易出錯超過2列...

而且,我的用例包括了多種類型(INT UNSIGNEDBINARY)列,但都相當的

你有什麼建議嗎?

謝謝!

回答

2

如果(在不幸命名)列Column_1是獨一無二的,你可能只是做:

WHERE Column_1 > :last_retrieved_value 

從這個問題,似乎Column_1不是唯一的,但(Column_1,Column_2)元組是唯一的。

一般形式的「下一頁」的查詢,由這兩列排序,使用最後的檢索值的兩列,將...

(Column1,Column2) > (:lrv_col1,:lrv_col2) 

(LRV =從保存的值)由以前的查詢檢索最後一行

要寫在MySQL這種條件下,我們可以這樣做,你已經證明:

WHERE t.Column_1 > :lrv_col1 
    OR (t.Column_1 = :lrv_col1 AND t.Column_2 > :lrv_col2) 

或者,我們可以把它寫這樣的,這是我願意的話,因爲有少得多一個機會讓MySQL能夠通過OR條件感到困惑,並使用了錯誤的指標...

WHERE t.Column_1 >= :lrv_col1 
     AND (t.Column_1 > :lrv_col1 OR t.Column_2 > :lrv_col2) 
ORDER BY t.Column_1, t.Column_2 
LIMIT n 

要延長到列,來檢查條件...

(c1,c2,c3) > (:lrv1,:lrv2,:lrv3) 

我們處理它就像兩列的情況下,處理c1第一,打破它就像兩列:

WHERE c1 >= :lrv1 
     AND (c1 > :lrv1 OR (...)) 
ORDER BY c1, c2, c3 
LIMIT n 

而現在,佔位符...(其中會剛我們需要檢查:(c2,c3) > (lrv2,lrv3),所以我們可以使用相同的模式擴展它:

WHERE c1 >= :lrv1 
     AND (c1 > :lrv1 OR (c2 >= :lrv2 
          AND (c2 > :lrv2 OR c3 > :lrv3) 
          ) 
      ) 
ORDER BY c1,c2,c3 
LIMIT n 

我同意擴展可能看起來有點混亂。但它確實遵循一個非常規則的模式。同樣,我們可以表達對列的條件...

(c1,c2,c3,c4) > (:lrv1,:lrv2,:lrv3,:lrv4) 

我們只是把我們所擁有的三列,我們需要擴大c3 > :lrv3(c3 >= :lrv3 AND (c3 > :lrv3 OR c4 > :lrv4))

來代替它
WHERE c1 >= :lrv1 
     AND (c1 > :lrv1 OR (c2 >= :lrv2 
          AND (c2 > :lrv2 OR (c3 >= :lrv3 
                AND (c3 > :lrv3 OR c4 > :lrv4) 
               ) 
           ) 
          ) 
      ) 
ORDER BY c1,c2,c3,c4 
LIMIT n 

作爲援助的未來讀者,我會評論此塊,並表示有意...

-- (c1,c2,c3,c4) > (lr1,lr2,lr3,lr4) 

如果MySQL允許我們表達比較就好了。不幸的是,我們必須將其擴展到MySQL理解的內容。

+0

感謝您的詳細解答! 我嘗試使用簡單的「元組」比較,它工作(MySQL 5.6)。嘗試運行一些'EXPLAIN'查詢來查看它是否比擴展版本更好... – amitayh

+0

哈!我不知道MySQL支持那個元組比較語法!比擴展更容易......(c1,c2,c3)>(r1,r2,r3)。是的,請檢查EXPLAIN計劃......我們希望MySQL使用索引範圍掃描操作,並將c1,c2,c3作爲主要列。 – spencer7593