按 random() 排序,在 SQLITE 中使用种子

2022-08-30 20:03:19

我想为随机集实现分页

Select * from Animals ORDER BY random(SEED) LIMIT 100 OFFSET 50  

我试图将int设置为某个整数和一些断裂。不起作用

如何在 sqlite 中随机播种?

我在这里用反对票抓住机会,因为类似的问题已经存在 - 播种SQLite RANDOM()。我只是没有得到php解决方案。


答案 1

简短的回答:

你不能。SQLite 的 random() 函数不支持种子值。

不是那么简短的答案:

检查 SQLite 的 func.c 表明 random() 的定义没有任何参数。

VFUNCTION(random,            0, 0, 0, randomFunc       ),

..这个 randomFunc() 只是调用 sqlite3_randomness() (同样没有任何显式种子值) 来获得一个大小为(sqlite_int64) 字节的随机值。

在内部,sqlite3_randomness()(参见 random.c)的实现将在 RC4 伪随机数生成器首次与从操作系统获得的随机种子值一起使用时设置它:

  /* Initialize the state of the random number generator once,
  ** the first time this routine is called.  The seed value does
  ** not need to contain a lot of randomness since we are not
  ** trying to do secure encryption or anything like that...
  **
  ** [..]
  */
  if( !wsdPrng.isInit ){
      [..]
      sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
      [..]
      wsdPrng.isInit = 1;
  }

实际上,SQLite的单元测试函数本身只是在全局sqlite3Prng结构上使用memcpy()在测试运行期间保存或恢复PRNG的状态。

所以,除非你愿意做一些奇怪的事情(比如创建一个连续数字的临时表(1..max(动物)),把这些数字洗牌并用它们从你的动物表中选择“随机种子”的RowIds),我想你运气不好。


答案 2

我通常不会复制现有的答案,但我可以看到你已经留下了一条评论,要求这个答案的作者在几周前解释它是如何工作的,并且没有给出任何解释。因此,我将复制相关部分,并试图解释发生了什么。如果这个解释很好,请去对原始答案进行投票。

$seed = md5(mt_rand());
$prng = ('0.' . str_replace(array('0', 'a', 'b', 'c', 'd', 'e', 'f'), array('7', '3', '1', '5', '9', '8', '4'), $seed )) * 1;
$query = 'SELECT id, name FROM table ORDER BY (substr(id * ' . $prng . ', length(id) + 2)';

前两行只是关于创建某种种子。结果是一个十进制数,其中包含许多小数,例如:

0.54534238371923827955579364758491

然后,sql 选择使用此数字与表中每一行的数字行 ID 相乘。然后根据结果产品的小数部分对行进行排序。使用较少的小数,排序顺序将如下所示:SQLite

row id   row id * seed      sort order
1        0.545342384        545342384
2        1.090684767        090684767
3        1.636027151        636027151
4        2.181369535        181369535
5        2.726711919        726711919
6        3.272054302        272054302
7        3.817396686        817396686
8        4.362739070        362739070

排序后,结果如下:

row id   row id * seed      sort order
2        1.090684767        090684767
4        2.181369535        181369535
6        3.272054302        272054302
8        4.362739070        362739070
1        0.545342384        545342384
3        1.636027151        636027151
5        2.726711919        726711919
7        3.817396686        817396686

在此示例中,我只使用了八行,因此结果看起来不是很随机。行越多,结果将显得更加随机。

此解决方案将反复为您提供相同的订单,只要:

  • 您使用相同的种子
  • 表中未出现任何新行,并且未从表中删除任何行

推荐