【问题标题】:SQLite - ORDER BY RAND()SQLite - 按兰德排序()
【发布时间】:2010-11-18 05:19:29
【问题描述】:

在 MySQL 中我可以使用 RAND() 函数,在 SQLite 3 中有什么替代方法吗?

【问题讨论】:

标签: sql mysql database sqlite random-access


【解决方案1】:

已解决:

SELECT * FROM table ORDER BY RANDOM() LIMIT 1;

【讨论】:

  • 我不同意。我们现在有两个信息,如何随机选择一条记录,如何随机列出所有记录。我从来不需要这样做,但如果我这样做,现在我知道该怎么做了。我也知道 MySQL 与 SQLlite 不同。一个超级技术问题会更令人印象深刻,但用处不大。
  • 我的第一个想法是没有任何函数可以随机排序结果,或者如果有这样的特性/函数,它会相当模糊 - 例如 SQLite 触发器就会发生这种情况。
【解决方案2】:
SELECT * FROM table ORDER BY RANDOM() LIMIT 1;

【讨论】:

  • 如果您想随机排序整个表并以该随机顺序访问所有行,则限制不必为 1。
  • 如果您有一个复杂的 WHERE 子句并且想要从该过滤列表中获得一个随机行,这也将起作用。接受的答案并不容易支持。
  • 还有一个结果中没有返回重复的行,这就是我需要的(y)
  • 为什么我使用它有这个错误信息的消息:第一个 ORDER BY 术语与结果集中的任何列都不匹配
【解决方案3】:

使用random()

SELECT foo FROM bar
  WHERE id >= (abs(random()) % (SELECT max(id) FROM bar))
  LIMIT 1;

编辑(按 QOP): 因为SQLite Autoincremented 列上的文档指出:

上面描述的普通ROWID选择算法会生成 只要您从不使用 最大 ROWID 值,并且您永远不会删除表中的条目 最大的 ROWID。 如果您曾经删除行,那么 ROWID 来自 创建新行时可能会重复使用以前删除的行

仅当您没有INTEGER PRIMARY KEY AUTOINCREMENT 列时,上述情况才成立(它仍然可以与INTEGER PRIMARY KEY 列一起使用)。无论如何,这应该更便携/可靠:

SELECT foo FROM bar
  WHERE _ROWID_ >= (abs(random()) % (SELECT max(_ROWID_) FROM bar))
LIMIT 1;

ROWID_ROWID_OID 都是 SQLite 内部行 ID 的别名。

【讨论】:

  • +1,如果 id 是索引,这比其他选项快得多。
  • 是的,这个解决方案更快,但假设 id 从 1 开始并且没有间隙。否则,间隙后面的行会比其他行更频繁地“随机”选择。
  • 同样最低的 ID 几乎永远不会被选中。
  • 哇,我的查询从 >300 毫秒变为 1 毫秒!
  • 非常好的解决方案,可以随机只生成 1 行,但在限制大于 1 时效果不佳:/ 事实上,我在 DDB 中仅使用 4 个输入进行了测试,限制为 5 => 有时我有 3 个结果,有时有 4 个结果...我认为更大的 DDB 会有更好的随机性,但对于小人来说不是。
【解决方案4】:

为了获得更好的性能,请在 SQLite 中使用:

SELECT * FROM table WHERE id IN (SELECT id FROM table ORDER BY RANDOM() LIMIT x) 

这也适用于 MySQL。这运行得更快,因为 SQL 引擎首先将行的投影字段加载到内存然后对其进行排序,这里我们只是加载行的 id 字段并随机排序,然后我们得到其中的 X 个,并找到整行默认情况下,这些 X id 被编入索引。

【讨论】:

  • +1。在我的环境中,这比 SELECT * FROM table ORDER BY RANDOM() LIMIT 1 快约 30 倍,并且仍然提供真正的随机,对表架构没有任何要求。
猜你喜欢
  • 1970-01-01
  • 2019-07-02
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多