从表中返回随机,无重复的行 – PostgreSQL

前端之家收集整理的这篇文章主要介绍了从表中返回随机,无重复的行 – PostgreSQL前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个有趣的问题,我正在寻找一些指导.
我有一个表“图像”,其中包含数千行.
我希望能够一次返回一组限制为50的随机行.

客户端,我有一个初始的GetImages()方法,它最初将返回50个“随机”图像(如果有那么多).当用户滚动它们并达到一定数量(大约40)时,另一个函数将触发 – GetMoreImages().

问题是我不知道如何在没有返回相同结果的风险的情况下检索更多图像.

例如,如果总共有60个图像,我希望GetMoreImages()调用仅返回剩余的10个图像.

我觉得我还应该提一下,我的Id表是非连续的,因为我正在使用Instagram方法(http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram)
这让我在每一行id之间留下了很大的差距.

我可以尝试的一种方法是传递我已经拥有的所有图像的id,但如果用户滚动数千张图像,这将变得笨拙.

我想另一种方法可能是在每个用户的应用程序服务器上存储缓存的“随机”值集,但我也不喜欢这个想法.

如果有任何最佳实践,你可以指导我,我们将不胜感激.

解决方法

您可以使用以下查询获取随机图像:

select *
from images
order by random()
limit 50;

我不是百分之百,以下将工作,但它可能.你想要的是一个随机生成器,它可以重现相同的值.为此,请使用setseed().所以,你可以这样做:

with t as (
      select setseed(1)
     )
select *
from images cross join t
order by random()
limit 50;

然后您可以获得后续值:

with t as (
      select setseed(1)
     ) 
select *
from images cross join t
order by random()
limit 50;

问题是随后的调用是否以完全相同的顺序调用random().您可以通过以下方式强制执行此操作:

with t as (
      select setseed(1)
     ),i as (
      select i.*,random() as rand
      from images i cross join t
     )
select *
from i
order by i.rand
limit 50;

但是,这仍假设对同一个表的多次调用将采用相同的顺序.
然后,您可以使用限制10偏移量50运行相同的查询,依此类推.

您可以使用计数器,与当前日期时间相关的函数或仅使用随机生成器来更改每个调用的种子值.

编辑:

我的常用方法是使用伪随机生成器.我只需要相对较大的素数,做一些算术并使用该值.

通过更改等式中的值,您可以根据需要调整参数.例如,我记得8,191和131,071是素数(因为它们是Mersenne素数).所以,我可能会这样做:

select i.*
from images i
order by mod(i.id * 8191 + 1,131071)
limit 50 offset xxx;

您可以调整“1”以创建不同的序列.这不是真正的“随机”,它取决于id是整数类型,但它避免了随机生成方法的不稳定性.这仍然是按顺序执行,因此可能效率低下,具体取决于数据的大小.

猜你在找的Postgre SQL相关文章