OFFSET x LIMIT y 打乱了行的顺序

O'N*_*iel 2 mysql

我有两张表,一张名为sale,一张名为voucher。销售包含一个purchase_date,凭证表包含一个 ID(我正在从问题中删除不相关的数据)。

我从数据库中选择 coupon.ID 和 sale.purchase_date,然后按日期降序对它们进行排序。

select  voucher.id, sale.purchase_date
    from  voucher
    inner join  sale  ON sale.id=voucher.sale
    order by  sale.purchase_date desc;
Run Code Online (Sandbox Code Playgroud)

这一切顺利: SQL选择

但我得到了很多行作为结果。为了避免网页上的初始加载时间过长,我想以五个部分加载结果。为此,我在 MySQL 中使用LIMITand commando。OFFSET

select  voucher.id, sale.purchase_date
    from  voucher
    inner join  sale  ON sale.id=voucher.sale
    order by  sale.purchase_date desc
    limit  5 offset 0;
Run Code Online (Sandbox Code Playgroud)

这看起来可行……但实际上它打乱了顺序。

做的时候

  • LIMIT 5 OFFSET 0,我期望ID:92,91,62,63,64(基于上图)
  • LIMIT 5 OFFSET 5,我期望 ID:65、66、67、68、69
  • LIMIT 5 OFFSET 10,我期望 ID:70、71、72、73、74
  • ...

但行以不同的顺序返回: SQL返回

不知何故,当使用偏移量和限制时,id 为 60 的行会以某种方式在前 5 个结果中获取。

使用偏移量和限制从查询中加载结果的最正确方法是什么?

SQLFiddle

O'N*_*iel 5

这是因为我在 上订购造成的purchase_date。但有多行具有完全相同的购买日期。MySQL 不保证在 order-clause 中具有相同投票数的行之间的多个查询的顺序一致。

在 order 子句中添加另一个唯一列可以解决该问题。

select  voucher.id, sale.purchase_date
    from  voucher
    inner join  sale  ON sale.id=voucher.sale
    order by  sale.purchase_date desc, voucher.id desc
    limit  x offset y;
Run Code Online (Sandbox Code Playgroud)

  • 这就解决了所问的问题。分页时通常还有两个问题——速度和数据变化时输出不一致。两者都在这里讨论:http://mysql.rjweb.org/doc.php/pagination (2认同)