MySQL游标基于多列的分页

ami*_*ayh 7 mysql pagination

我有一些表,我想使用基于游标的分页查询,但它需要申请多个列.

让我们看一个使用2列的简化示例 - 我像这样获取第一页:

SELECT column_1, column_2
FROM table_name
ORDER BY column_1, column_2
LIMIT 10
Run Code Online (Sandbox Code Playgroud)

在我得到结果后,我可以根据最后一行获取下一页.让我们说最后一行是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
Run Code Online (Sandbox Code Playgroud)

但这显然是错误的.它会过滤掉一行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
Run Code Online (Sandbox Code Playgroud)

但是这对于超过2列来说变得非常麻烦并且容易出错...

此外,我的用例包括多种类型(INT UNSIGNEDBINARY)的列,但所有列都具有可比性

你有什么建议吗?

谢谢!

spe*_*593 10

如果(遗憾地命名)列Column_1是唯一的,您可以这样做:

 WHERE Column_1 > :last_retrieved_value
Run Code Online (Sandbox Code Playgroud)

从问题来看,它似乎Column_1并不是唯一的,但(Column_1,Column_2)元组是独一无二的.

"下一页"查询的一般形式,按这两列排序,使用这两列的最后检索值,将是......

    (Column1,Column2) > (:lrv_col1,:lrv_col2)
Run Code Online (Sandbox Code Playgroud)

(lrv =从上一个查询检索的最后一行保存的值)

要在MySQL中编写该条件,我们可以像您所示的那样:

 WHERE t.Column_1 > :lrv_col1
    OR ( t.Column_1 = :lrv_col1 AND t.Column_2 > :lrv_col2 )
Run Code Online (Sandbox Code Playgroud)

或者,我们可以像这样写它,我更喜欢,因为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
Run Code Online (Sandbox Code Playgroud)

要将其扩展到列,检查条件......

  (c1,c2,c3) > (:lrv1,:lrv2,:lrv3)
Run Code Online (Sandbox Code Playgroud)

我们处理它就像在两列的情况下一样处理,c1首先处理它,就像两列一样:

 WHERE c1 >= :lrv1
       AND ( c1 > :lrv1 OR ( ... ) )
 ORDER BY c1, c2, c3
 LIMIT n
Run Code Online (Sandbox Code Playgroud)

而现在那个占位符...(之前只会进行检查c2,实际上又是两列的另一种情况.我们需要检查:(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
Run Code Online (Sandbox Code Playgroud)

我同意扩张可能看起来有些混乱.但它确实遵循非常规律的模式.同样,我们可以在列上表达条件......

 (c1,c2,c3,c4) > (:lrv1,:lrv2,:lrv3,:lrv4)
Run Code Online (Sandbox Code Playgroud)

我们只需要对三列进行处理,我们需要扩展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
Run Code Online (Sandbox Code Playgroud)

作为未来读者的帮助,我会评论这个块,并表明意图......

 -- (c1,c2,c3,c4) > (lr1,lr2,lr3,lr4)
Run Code Online (Sandbox Code Playgroud)

如果MySQL允许我们像这样表达比较,那将是很好的.不幸的是,我们必须将其扩展为MySQL理解的东西.

  • 复杂的替代方案通过同时使用“>”和“<”运算符来混合“ASC”和“DESC”,从而增加了灵活性。 (5认同)