2016-06-24 36 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