如何对按降序排序的查询结果进行分页

时间:2014-08-09 14:18:31

标签: mysql sql pagination ebean

我正在建立我的应用程序的后台,我希望以递减ID的形式订购最后20个用户。

我在页面中实现了无限滚动,因此每次管理员点击页面底部时,都会通过Ajax发送新请求以检索20个以下用户等等...直到我们得到第一个用户

总之,以下是几个查询:

select * from users order by id desc limit 0, 20
select * from users order by id desc limit 20, 20
select * from users order by id desc limit 40, 20
...

但问题是我按降序排序用户。因此,如果新用户在我滚动时进行注册,则每次发送请求时都会出现重复结果。

我们说我的用户列表如下,我的限制是3(而不是20)

1. Pierre
2. Paul
3. Jack
4. Jean
5. Mike
  • 第一个问题会给我:Mike,Jean,Jack
  • 第二个:Paul,Pierre

但如果用户" Carla"在两个请求之间进行注册:

  • 第一个查询仍然会给我:Mike,Jean,Jack
  • >> Carla注册并获得ID 6
  • 第二个:杰克,保罗,皮埃尔

结论是我将有记录"杰克"在我的桌子上两次。

这个问题看起来很荒谬,但你知道如何避免这种情况吗?

PS:我不知道你是否注意到它,但Facebook似乎有类似的问题,当你向下滚动新闻源时,你可以看到相同项目的几次。它必须是一个更复杂的问题,但想法是一样的。

3 个答案:

答案 0 :(得分:2)

我认为你基本上有两种解决这个问题的现实方法。一种不切实际的方法是在浏览时锁定表 - 然后新用户无法进入。另一种方法是在每个用户启动页面时为其创建一个临时表。呸!

第二种是在用户注册时加上时间戳。然后获取此时间戳并使用它进行滚动。您需要从数据库中获取时间戳,以避免应用程序端和数据库端的时间略有不同。类似的东西:

select now() as as_of_date

然后将其放入变量并将查询更改为:

select * from users where CreationTime <= @as_of_date order by id desc limit 0, 20;
select * from users order CreationTime <= @as_of_date by id desc limit 20, 20;
select * from users order CreationTime <= @as_of_date by id desc limit 40, 20;

请注意,在更新版本的MySQL中,您可以将当前时间设置为datetime时间的默认值(而不是为此目的而处理timestamp。)

答案 1 :(得分:1)

如果您不想看到新创建的用户,解决方案将相对简单。如果id是自动序列 - 您可能会在运行检索查询之前捕获max(id),并将查询更新为 -

select * from users where id <= max_id order by id desc limit 0, 20

如果表格中有time stamp列,您可以与last_created类似。

如果您想要在输出中包含新创建的用户而不重复结果,则需要额外的逻辑。

希望这有帮助。

答案 2 :(得分:1)

试试这个

SELECT * FROM users WHERE id < PREVIOUS_LIST_LAST_ID ORDER BY id DESC LIMIT 3

对于每个请求,我们都可以发送id,这表示我们已经显示了结果。

但是如果你想显示新插入的记录,你也可以尝试

SELECT * FROM users WHERE id < PREVIOUS_LIST_MIN_ID OR id > MAX_ID
    ORDER BY id DESC LIMIT 3

在这种情况下,MAX_ID将是页面上可见的第一条记录的值