我想实现随机集的分页
Select * from Animals ORDER BY random(SEED) LIMIT 100 OFFSET 50
我试图将int设置为某个整数和某些断裂。不行吗
如何在sqlite中随机播种?
由于类似的问题已经存在,我在这里抓住了一个机会 - Seeding SQLite RANDOM()。我只是没有得到php解决方案。
答案 0 :(得分:15)
简答:
你不能。 SQLite的random()函数不支持种子值。
答案不是那么简短:
检查SQLite的func.c表明random()是在没有任何参数的情况下定义的。
VFUNCTION(random, 0, 0, 0, randomFunc ),
..而这个randomFunc()只调用sqlite3_randomness()(再次没有任何显式种子值)来获得 sizeof(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(动物)),然后将它们改组并用它们来选择随机播种的&#39 #39;来自动物表的RowIds)我想你运气不好。
答案 1 :(得分:6)
我通常不会复制现有的答案,但我可以看到你已经发表评论,要求this answer的作者在几周前解释它是如何运作的,并且没有给出任何解释。因此,我将复制相关部分,并尝试解释最新情况。如果这个解释很好,请去原始答案投票。
$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 select使用此数字乘以SQLite
表中每行的数字行id。然后根据结果产品的小数部分对行进行排序。使用较少的小数,排序顺序如下所示:
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
在这个示例中,我只使用了8行,因此结果不是很随机。如果行数越多,结果就越随机。
只要符合以下条件,此解决方案就会重复提供相同的订单:
答案 2 :(得分:1)
我不知道您是否想要PHP 和 iOS解决方案,但如果您只对iOS感兴趣并且不关心使用内置的sqlite random()函数,你可以声明一个自定义函数在你的查询中使用,它确实带有一个种子参数。
sqlite3_create_function(database, "CUSTOM_RANDOM", 1, SQLITE_UTF8, NULL, &CustomRandomSQLite, NULL, NULL);
void CustomRandomSQLite(sqlite3_context* context, int argc, sqlite3_value** argv)
{
if(argc == 1 && sqlite3_value_type(argv[0]) == SQLITE_INTEGER)
{
const int seed = sqlite3_value_int(argv[0]);
const int result = ...;
sqlite3_result_int(context, result);
}
else
{
sqlite3_result_error(context, "Invalid", 0);
}
}
Select * from Animals ORDER BY CUSTOM_RANDOM(SEED) LIMIT 100 OFFSET 50
答案 3 :(得分:-1)
我在javascript游戏中从种子中随机使用这个我相信你可以很容易地将它转换为sql
seed: function(max) {
if(typeof this._random === 'undefined') this._random = max; // init on first run
this._random = (this._random * 9301 + 49297) % 233280;
return Math.floor(this._random / (233280.0) * max);
}