我正在建立我的应用程序的后台,我希望以递减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
但如果用户" Carla"在两个请求之间进行注册:
结论是我将有记录"杰克"在我的桌子上两次。
这个问题看起来很荒谬,但你知道如何避免这种情况吗?
PS:我不知道你是否注意到它,但Facebook似乎有类似的问题,当你向下滚动新闻源时,你可以看到相同项目的几次。它必须是一个更复杂的问题,但想法是一样的。
答案 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将是页面上可见的第一条记录的值