在SQLite中选择随机行

在SQLite中选择随机行,sql,sqlite,Sql,Sqlite,在MySQL中,您可以使用以下语句选择X个随机行: SELECT * FROM table ORDER BY RAND() LIMIT X 但是,这在SQLite中不起作用。是否有等效项?按随机极限X从表顺序中选择* 要获得更好的性能,请使用: SQL引擎首先将行的投影字段加载到内存中,然后对它们进行排序,这里我们只是对内存中每一行的id字段进行随机排序,因为它已被索引,然后分离其中的X个字段,并使用这些X id查找整行 所以,随着表的增长,这将消耗更少的RAM和CPU 这里的所有答案都是根据

在MySQL中,您可以使用以下语句选择X个随机行:

SELECT * FROM table ORDER BY RAND() LIMIT X
但是,这在SQLite中不起作用。是否有等效项?

按随机极限X从表顺序中选择* 要获得更好的性能,请使用:

SQL引擎首先将行的投影字段加载到内存中,然后对它们进行排序,这里我们只是对内存中每一行的id字段进行随机排序,因为它已被索引,然后分离其中的X个字段,并使用这些X id查找整行


所以,随着表的增长,这将消耗更少的RAM和CPU

这里的所有答案都是根据顺序排列的。这是非常低效的,即对于大型集合不可用,因为您将对每个记录进行随机评估,然后按顺序进行操作,这是一个资源昂贵的操作

另一种方法是在WHERE子句中将absCASTrandom设置为REAL/9223372036854775808<0.5,在本例中,例如0.5命中率

SELECT *
FROM table
WHERE abs(CAST(random() AS REAL))/9223372036854775808 < 0.5
大数是可以产生的最大绝对数。abs是因为它有签名。结果是0和1之间的均匀分布随机变量


这有它的缺点。您无法保证结果,如果阈值与表相比较大,则所选数据将向表的开头倾斜。但在一些精心设计的情况下,它可能是一个可行的选择。

此选项解决负随机整数,并在大型数据集上保持良好的性能:

SELECT * FROM table LIMIT 1 OFFSET abs(random() % (select count(*) from table));
其中:
absrandom%n为您提供一个范围为0的正整数,n

接受的答案有效,但每个查询需要进行完整的表扫描。随着表变大,这将变得越来越慢,这使得由最终用户触发的查询具有风险

以下解决方案利用索引在OlogN时间内运行

从表中选择* 其中rowid> ABSRANDOM%从表中选择maxrowid 限值1; 打破它

从表中选择maxrowid-返回表的最大有效rowid。为了有效地运行这个。 ABSRANDOM%…-返回一个介于0和maxrowid-1之间的随机数。生成一个介于-9223372036854775808和+9223372036854775807之间的数字。ABS确保其为正,模数运算符将其选通到maxrowid-1之间。 rowid>…-如果生成的随机数对应于已删除的行,请使用>而不是使用=。使用“严格大于”可以确保返回的行的行id介于1大于0和maxrowid大于maxrowid-1之间。SQLite也使用主键索引高效地返回此结果。 这也适用于带有WHERE子句的查询。将WHERE子句应用于输出和SELECT maxrowid子查询。但是,我不确定这在哪些条件下会有效运行


注意:这是从。

中派生出来的记录:这是可行的,但在较大的表上速度较慢。一种更快的方法(虽然不完全相同)是:从表中选择*,其中随机%k=0限制n;。这样做的缺点是主键较低的记录被选中的几率较高。是的,在大表上它会很慢,因为它最终会强制进行表扫描。希望在SQL中执行类似操作的缺点。最好的方法是在前端随机选取偏移量。其中一种方法2比公认的答案快得多。谢谢这真是太棒了,谢谢,我已经更新了公认的答案:按随机顺序有多随机?因为我不觉得这是真的随机。。。有一组非常频繁选择的行。。。难道没有人有同样的感觉吗?我应该总是使用limit 1还是我可以使用fethone使用sqlite3 python?对于想知道Alex的评论指的是什么的人来说,答案是用来显示2个方法的,而当前显示的是方法2。我猜唐尼的另一个答案曾经是公认的答案。
SELECT *
FROM table
WHERE abs(CAST(random() AS REAL))/9223372036854775808 < 0.5
SELECT * FROM table LIMIT 1 OFFSET abs(random() % (select count(*) from table));