且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

基于 MySQL 游标的多列分页

更新时间:2023-02-02 22:06:55

如果(不幸命名的)列 Column_1 是唯一的,你可以这样做:

If (the unfortunately named) column Column_1 is unique, you could just do:

 WHERE Column_1 > :last_retrieved_value

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

From the question, it appears that Column_1 is not unique, but the (Column_1,Column_2) tuple is unique.

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

The general form for a "next page" query, ordering by those two columns, using the last retrieved values for those two columns, would be...

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

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

(lrv = value saved from the last row retrieved by the previous query)

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

To write that condition in MySQL, we can do that like you have shown:

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

或者,我们可以这样写,我更喜欢这样,因为 MySQL 被 OR 条件混淆并使用错误索引的可能性要小得多......

Or, we could write it like this, which I prefer, because there's much less of a chance for MySQL to get confused by the OR condition and use the wrong index...

 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

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

To extend that to three columns, to check the condition...

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

我们像处理两列一样处理它,首先处理 c1,然后像两列一样将其分解:

We handle it just like in the case of two columns, handling c1 first, breaking it out just like the two columns:

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

现在占位符 ...(之前只检查 c2 的地方,实际上又只是两列的另一种情况.我们需要检查: (c2,c3) > (lrv2,lrv3),所以我们可以使用相同的模式扩展它:

And now that placeholder ... (where would have had just the check on c2 before, is really again just another case of two columns. We need to check: (c2,c3) > (lrv2,lrv3), so we can expand that using the same pattern:

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

我同意扩展可能看起来有点乱.但它确实遵循一个非常规律​​的模式.类似地,我们可以在列上表达条件...

I agree that the expansion may look a little messy. But it does follow a very regular pattern. Similarly, we could express the condition on four columns...

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

我们只取三列的内容,我们需要展开 c3 >:lrv3 将其替换为 ( c3 >= :lrv3 AND ( c3 > :lrv3 OR c4 > :lrv4 ) )

We just take what we have for the three columns, and we need to expand c3 > :lrv3 to replace it with ( 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

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

As an aid the the future reader, I would comment this block, and indicate the intent ...

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

如果 MySQL 允许我们像这样表达比较,那就太好了.不幸的是,我们必须将其扩展为 MySQL 能够理解的内容.

And it would be nice if MySQL would allow us to express the comparison just like that. Unfortunately, we have to expand that into something MySQL understands.