在MySQL中,您可以使用以下语句选择X随机行:
SELECT * FROM table ORDER BY RAND() LIMIT X
然而,这不适用于SQLite。有没有等价的?
答案 0 :(得分:65)
对于更好的性能使用:
SELECT * FROM table WHERE id IN (SELECT id FROM table ORDER BY RANDOM() LIMIT x)
SQL引擎首先将行的预计字段加载到内存然后对它们进行排序,这里我们只是对内存中每行的id字段进行随机排序,因为它已编入索引,然后将它们分开,并使用这些X ID找到整行。
因此,随着表的增长,这会占用更少的RAM和CPU!
答案 1 :(得分:58)
SELECT * FROM table ORDER BY RANDOM() LIMIT X
答案 2 :(得分:8)
SELECT * FROM table ORDER BY RANDOM() LIMIT 1
答案 3 :(得分:2)
此处的所有答案均基于ORDER BY
。对于大型集合,非常效率低(即无法使用),因为您将为每条记录评估RANDOM()
,然后ORDER BY
这是一项资源昂贵的操作。
另一种方法是将abs(CAST(random() AS REAL))/9223372036854775808 < 0.5
放在WHERE
子句中,以获得0.5例命中率。
SELECT *
FROM table
WHERE abs(CAST(random() AS REAL))/9223372036854775808 < 0.5
大数是random()
可以产生的最大绝对数。 abs()
是因为它已签名。结果是0到1之间的均匀分布随机变量。
这有其缺点。您无法保证结果,如果阈值与表相比较大,则所选数据将偏向表的开头。但在一些精心设计的情况下,它可能是一个可行的选择。
答案 4 :(得分:2)
接受的答案有效,但需要对每个查询进行全表扫描。随着您的表变大,这将变得越来越慢,从而使最终用户触发的查询存在风险。
以下解决方案利用索引在 O(log(N)) 时间内运行。
SELECT * FROM table
WHERE rowid > (
ABS(RANDOM()) % (SELECT max(rowid) FROM table)
)
LIMIT 1;
分解
SELECT max(rowid) FROM table
- 返回表的最大有效 rowid。 SQLite is able to use the index on rowid
以高效运行。ABS(RANDOM()) % ...
- 返回一个介于 0 和 max(rowid) - 1)
之间的随机数。 SQLite's random
function 生成一个介于 -9223372036854775808 和 +9223372036854775807 之间的数字。 ABS
确保其为正数,模运算符将其在 max(rowid) - 1
之间进行门控。rowid > ...
- 如果生成的随机数对应于已删除的行,请使用 =
而不是使用 >
。使用严格大于可确保我们返回行 ID 介于 1(大于 0)和 max(rowid)
(大于 max(rowid) - 1
)之间的行。 SQLite 也使用主键索引来有效地返回此结果。这也适用于带有 WHERE
子句的查询。将 WHERE
子句应用于输出和 SELECT max(rowid)
子查询。但是,我不确定这将在哪些条件下有效运行。
注意:这是从 an answer in a similar question 派生的。
答案 5 :(得分:0)
这解决了负RANDOM整数,并在大型数据集上保持了良好的性能:
SELECT * FROM table LIMIT 1 OFFSET abs(random() % (select count(*) from table));
其中:
abs(random() % n )
在range(0,n)
中给您一个正整数