随机排序的行可重复分页

use*_*521 12 random postgresql pagination random-seed

我有API从DB返回圆顶分页行.它工作正常,但是当我按行排序时,RANDOM()我会在连续的页面上重复.是否有任何选项可以为每个查询设置随机种子?

如果不是可以全局设置随机SEED以强制RANDOM()为每个查询生成相同的值?然后我可以每隔3分钟改变全局随机或类似的东西......


你用这个代码:

SELECT * FROM "table" ORDER BY RANDOM() OFFSET 5 LIMIT 5
Run Code Online (Sandbox Code Playgroud)

现在我想传递种子到这个查询,所以我可以分页随机结果.我应该这样做?:

SELECT "table".*, SETSEED(0.1) FROM "table" ORDER BY RANDOM() OFFSET 5 LIMIT 5
SELECT "table".*, SETSEED(0.1) FROM "table" ORDER BY RANDOM() OFFSET 10 LIMIT 5
Run Code Online (Sandbox Code Playgroud)

结果将正确分页?

Nat*_*ong 8

如果订单需要"洗牌"但不是真正随机的......

你说"随机"顺序,这是你在调用时获得的ORDER BY random()- 对于每一行,PostgreSQL调用random(),获取一个值,并使用它来决定如何在结果集中对该行进行排序.

为了使这个可重复,你必须弄乱种子.这感觉很蠢.根据文件:

效果将持续到会话结束,除非被另一个SET覆盖

我认为这意味着在使用连接池时,会setseed改变使用该连接的下一个进程的连接.

模数怎么样?

我有一个案例,我不需要真正的随机性.我的标准是:

  • 每次都不一样
  • 在同一结果集的页面内可预测的顺序,这样我们就不会在后续页面上获得重复

例如,这没关系:

  • 清单1
    • 第1页:第1,4项
    • 第2页:第3项,第2项
  • 清单2(不同的用户,或稍后回来的同一用户)
    • 第1页:第3项,第1项
    • 第2页:第2项,第4项

为了获得这样的东西,模数似乎运作良好.例如,ORDER BY id % 7, id对于请求1 ORDER BY id % 11, id的所有页面,以及请求2的所有页面.即,对于每一行,将其id除以模数并按余数排序.在具有相同余数的行中,按id排序(以确保排序稳定).

可以为第一页随机选取模数,然后将其重新用作每个后续页面请求的参数.

你可以看到这对你的数据库如何有用:

echo "select id, id % 7 FROM my_table ORDER BY id % 77, id" | psql my_db > sort.txt
Run Code Online (Sandbox Code Playgroud)

素数模数可能会给你最大的变化.如果你的id从1开始(这样% 77会使前77行以正常顺序返回),你可以尝试在时间戳字段上执行模数.例如:

ORDER BY (extract(epoch from inserted_at)* 100000)::bigint % 77

但是你需要一个函数索引来提高性能.


Clo*_*eto 5

使用这种union all技术,随机顺序是可重复的

select a, b
from (
    select setseed(0.1), null as a, null as b

    union all

    select null, a, b
    from t

    offset 1
) s
order by random()
offset 0
limit 5
;
Run Code Online (Sandbox Code Playgroud)


Mur*_*nik 2

您可以使用[-1.0, 1.0] 中的种子进行setseed(dp)播种。random()例如:

engine=> SELECT SETSEED(0.16111981);
 setseed 
---------

(1 row)

engine=> SELECT RANDOM();
      random       
-------------------
 0.205839179921895
(1 row)

engine=> SELECT RANDOM();
      random       
-------------------
 0.379503262229264
(1 row)

engine=> SELECT RANDOM();
      random       
-------------------
 0.268553872592747
(1 row)

engine=> SELECT RANDOM();
      random       
-------------------
 0.788029655814171
(1 row)
Run Code Online (Sandbox Code Playgroud)

当然,每次重新播种时,您都会得到完全相同的结果:

engine=> SELECT SETSEED(0.16111981), RANDOM();
 setseed |      random       
---------+-------------------
         | 0.205839179921895
(1 row)

engine=> SELECT SETSEED(0.16111981), RANDOM();
 setseed |      random       
---------+-------------------
         | 0.205839179921895
(1 row)

engine=> SELECT SETSEED(0.16111981), RANDOM();
 setseed |      random       
---------+-------------------
         | 0.205839179921895
(1 row)

engine=> SELECT SETSEED(0.16111981), RANDOM();
 setseed |      random       
---------+-------------------
         | 0.205839179921895
Run Code Online (Sandbox Code Playgroud)

(澄清:输出是从 复制的psql,引擎是我的数据库的名称)