【问题标题】:generating 10 random id numbers form a table in a string生成 10 个随机 id 数字形成字符串中的表
【发布时间】:2019-07-17 12:42:06
【问题描述】:

我有一个 id 表,从 1 到 30

|  id  |
|  1   |
|  2   |
|  3   |
|  4   |
|  5   |
|  .   |
|  .   |
|  .   |
|  30  |

我想要做的是在这样的字符串中从中获取 10 个随机 id

(1,2,3,4,5,6,7,8,9,10)

我发现是

https://www.db-fiddle.com/f/3gTHLSTdFEac7dKbDcU43d/3

https://www.db-fiddle.com/f/3gTHLSTdFEac7dKbDcU43d/4

SELECT
    CONCAT_WS(", ",
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids)),
        CEIL(RAND() * (SELECT MAX(id) FROM ids))
    ) AS random_ids

有没有不使用ORDER BY RAND()的更快更高效的方法?

还有没有办法让它们变得独一无二,就像在它们之间留出空隙一样?

【问题讨论】:

  • 你能在这 10 个中允许重复的 id 吗?
  • @SalmanA 是的,如果有办法实现唯一性,那就太好了
  • 如果你想要的只是 10 个 1 到 30 之间的随机数,那么表格的意义何在?
  • @Strawberry 可以有更多的 id,所以最大 id 是可变的
  • 不过,我想我只是找到最大值并在此基础上在应用程序代码中生成 10 个随机数

标签: mysql sql random


【解决方案1】:
SELECT `id` FROM `table` ORDER BY RAND() LIMIT 10

更新小提琴:https://www.db-fiddle.com/f/3gTHLSTdFEac7dKbDcU43d/1

编辑:问题已更新为排除 ORDER BY RAND()

您可以执行多个查询。一个获取数据库中的记录数,然后使用OFFSET 一次选择一个随机值。我相信这会阻止全表扫描,并且比在大型数据集上使用简单的ORDER BY RAND() 更快。

更新了 fiddle 使用这种技术选择一个随机 id:https://www.db-fiddle.com/f/3gTHLSTdFEac7dKbDcU43d/5

SET @r := (SELECT FLOOR(RAND() * (SELECT COUNT(*) FROM `table`)));
SET @sql := CONCAT('SELECT `id` FROM `table` LIMIT 1 OFFSET ', @r);
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

信用:Selecting random rows with MySQL

【讨论】:

  • 我曾考虑过使用 ORDER BY RAND(),但它使用全扫描并导致查询速度变慢
  • 这是非常低效的(对于大型表),因为它将首先为表中的每条记录生成一个随机数,然后按该数字对所有记录进行排序,然后只返回前 10 条。想象一下这样做在数百万条记录的表上...对于具有 30 条记录的表...嗯。
  • 当然,但问题非常具体,他们有 30 个 id。它在 db-fiddle 上运行 80 毫秒。
【解决方案2】:

您可以使用ORDER BY RAND(),后跟GROUP_CONCAT

SELECT GROUP_CONCAT(id SEPARATOR ', ') AS random_ids
FROM (
    SELECT id
    FROM t
    ORDER BY RAND()
    LIMIT 10
) AS x

【讨论】:

  • 我不想使用order by rand(),因为它会进行全面扫描,可能是重写我的查询的更短方法
  • 恐怕没有其他解决方案了。如果它是随机的,那么每一行都有相同的机会被选中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
  • 2017-08-01
  • 2011-06-30
  • 1970-01-01
相关资源
最近更新 更多