SQL - SELECT ... LIMIT [X] OFFSET [Y],不包括先前的记录

时间:2015-07-06 17:50:43

标签: mysql sql database relational-database

在MySQL中,我有一个简单的SELECT查询,可根据特定条件(num_likes,num_comments等)对帖子进行排序。

为了将这些帖子加载到我的应用程序中,我使用LIMIT和OFFSET来显示每页的n个帖子数量。但是,由于插入了新记录,SELECT查询的结果可能会发生变化。因此,以前的结果可能会重新出现在后续页面中。

是否可以防止这种情况发生?

3 个答案:

答案 0 :(得分:0)

创建以前查询中出现的ID的二进制搜索树,并将其与当前查询中的ID进行比较。如果有重复的ID,请不要显示这些记录。

它是一种简单的O(logn)算法。

答案 1 :(得分:0)

是的,可以避免/防止这种情况发生。一种方法是避免使用 LIMIT m,n (或LIMIT n OFFSET m ), and just use ** LIMIT n` **,以及来自"已保存的"值上一页上最​​后一行。

使用查询中保存的值来获取下一页。

假设此查询返回要显示的行的第一页:

  SELECT t.num_likes
       , ...
       , t.id
  ORDER BY t.num_likes DESC, t.id DESC
  LIMIT $pagesize

我们为最后一行保留idnum_likes的值,以便在下一个查询中使用。对于" next"查询,我们使用这样的值:

  SELECT t.num_likes
       , ...
       , t.id
   FROM mytable t
  WHERE t.num_likes <= :last_seen_num_likes 
    AND (t.num_likes < :last_seem_num_likes OR t.id < :last_seen_id)
  ORDER BY t.num_likes DESC, t.id DESC
  LIMIT $pagesize

例如,如果页面上的最后一行是num_likes=214id=42,那么查询将获得接下来的50行:

  SELECT t.num_likes
       , ...
       , t.id
   FROM mytable t
  WHERE t.num_likes <= 214
    AND (t.num_likes < 214 OR t.id < 42)
  ORDER BY t.num_likes DESC, t.id DESC
  LIMIT 50

使用此方法基本上保留了行列表中的位置,即使之前添加了行也是如此。我们不是尝试重新计算到同一位置,而是使用保留值来保留我们在列表中的位置。

如果你想启用&#34;之前的&#34;页面功能,也保留了&#34;首次出现的&#34;行,你可以运行类似的查询,只需翻转不等式比较的方向。

(这没有解决num_likes在查询之间更改行的问题,有效地重新排序列表中的那一行。)

答案 2 :(得分:0)

将最后一项的id显示为SQL的一个参数。然后更改您的代码,以便在按下“下一页”时,它会返回相关项之后的前n个项目。