mysql Seeding SQLite RANDOM()

vngu2lb8  于 2023-04-19  发布在  Mysql
关注(0)|答案(3)|浏览(118)

SQLite是否像MySQL支持**RAND()一样支持RANDOM()**函数的种子?

$query = "SELECT * FROM table ORDER BY RAND(" . date('Ymd') . ") LIMIT 1;";

来自RAND(N)的MySQL手册:

如果指定了一个常量整数参数N,它将被用作种子值,这将产生一个可重复的列值序列。在下面的示例中,请注意,兰德(3)产生的值序列在它出现的两个位置都是相同的。
如果没有,是否有任何方法可以只使用一个查询来归档相同的效果?

ncecgwcz

ncecgwcz1#

看看sqlite3_randomness()函数:
SQLite包含一个高质量的伪随机数生成器(PRNG),用于在向已经使用最大可能ROWID的表中插入新记录时选择随机ROWID。PRNG也用于内置的random()和randomblob()SQL函数。
...
第一次调用此例程时(内部调用或应用程序调用),PRNG将使用从默认sqlite3_vfs对象的xRandomness方法获得的随机性进行播种。在所有后续调用中,伪随机性将在内部生成,而无需求助于sqlite3_vfs xRandomness方法。
查看这个xRandomness方法的源代码,你可以看到它在Unix上从/dev/urandom读取。在Windows上,它只是返回一些时间函数的返回值。所以看起来你唯一的选择就是开始破解SQLite源代码。

anauzrmj

anauzrmj2#

如果你需要一个伪随机顺序,你可以这样做(PHP):

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

另外,您可以将$seed设置为预定义的值,并始终获得相同的结果。
我从我的同事http://steamcooker.blogspot.com/那里学到了这个技巧

qaxu7uf2

qaxu7uf23#

基于@jankkhvej的答案,我将修改代码,以使用预定义的种子(整数-32位数字)控制生成PRNG并记录代码。
实际上,PHP中的种子是使用函数mt_srand($seed)定义的

//define seed (modify it as needed), so you can get the same series every time you run the code.
$seed=123456789;
//mt_srand — Seeds the Mersenne Twister Random Number Generator
mt_srand($seed);

//compute hash md5 for mt_rand()
$md5 = md5(mt_rand());
//use md5 to get a decimal number by replacing the hex-decimal chars abcef by numeric values, then prefix the result with "0."
$prng = ('0.' . str_replace(['0', 'a', 'b', 'c', 'd', 'e', 'f'], ['7', '3', '1', '5', '9', '8', '4'], $md5 )) * 1;

//sqlite is using rowid, a unique number for row. If you defined a primary key, it can be rowid. 
//multiply rowid by $prng , and extract only the fraction part using substr function
//e.g 1.0519815151568 will be   0519815151568
$query = "SELECT id, name FROM table ORDER BY (substr(rowid * $prng , length(rowid) + 2))";

试试onlin demo
输出

seed= 1234567890
mt_rand= 1328851649
MD5 hash= 1abfd768d39fc907c278ec2cb8ae809b
prng= 0.1314976893946
SQLite version 3.7.17
Selecting 3 random rows of 10, with PRNG: 0.1314976893946
Id  name    rowid*prng         random
8   p_8     1.0519815151568    0519815151568
1   p_1     0.1314976893946    1314976893946
10  p_10    1.314976893946     14976893946

我提供了生成PNRG的替代解决方案,您可以找到here

相关问题