【问题标题】:MySQL lookup based on round(1 + rand() * x) produces NULL and multiple resultsMySQL 基于 round(1 + rand() * x) 查找产生 NULL 和多个结果
【发布时间】:2018-11-28 16:25:51
【问题描述】:

我正在尝试从 MySQL 中的查找表中随机选择名字来构建测试数据集。我有一个包含 200 个名字、性别和从 1 到 200 的行 ID 的表。像这样:

id   firstname   gender
1    Aaron       m
2    Adam        m
3    Alan        m
etc...

我正在使用 random generator 和以下查询从该表中进行选择:

SELECT id, firstname FROM firstname WHERE id = round(1 + (rand() * 199));

我希望随机数与查找表中的一个 id 完全一致,从而产生一个类似的结果

id   firstname
43   Jason

一次又一次地运行代码给了我一个选择

  • 单行(如上)
  • 多行,如

id firstname 29 Ethan 147 Jean

  • 没有结果(两个字段都为 NULL)。

如果我自己运行随机生成器,它总是会生成一个介于 1 和 200 之间的数字。如下所示,id 字段是 INT,如果我将结果转换为 SIGNED,查询的行为方式相同.我也尝试使用 FLOOR 而不是 ROUND,只是想看看效果是否有任何不同 - 唉,不。

谁能告诉我异常的原因?我错过了什么?

这里有一些代码用于创建原始表的前 20 行以用于测试目的:

-- First Name --
drop table if exists firstname;

  CREATE TABLE firstname (
  id INT NOT NULL,
  firstname VARCHAR(20) NOT NULL,
  gender VARCHAR(1) NOT NULL,
  PRIMARY KEY (id),
  UNIQUE (firstname)
  );

  INSERT INTO firstname
  (id,firstname,gender)
  VALUES
  (1,"Aaron","m"),
(2,"Adam","m"),
(3,"Alan","m"),
(4,"Albert","m"),
(5,"Alexander","m"),
(6,"Andrew","m"),
(7,"Anthony","m"),
(8,"Arthur","m"),
(9,"Austin","m"),
(10,"Benjamin","m"),
(11,"Billy","m"),
(12,"Bobby","m"),
(13,"Brandon","m"),
(14,"Brian","m"),
(15,"Bruce","m"),
(16,"Bryan","m"),
(17,"Carl","m"),
(18,"Charles","m"),
(19,"Christian","m"),
(20,"Christopher","m");

【问题讨论】:

  • 您可以使用SELECT id, firstname FROM firstname order by rand() limit 1 代替连接和生成器。
  • 漂亮而紧凑,但经过多次测试,结果相对同质,因为每个结果的数量变化(我正在用随机生成的记录填充大表)相当大小的。在 200 个名称和 10K 条记录中,出现的次数将介于 30 到 70 之间,大多数约为 50。我需要一个完全随机的结果,其中一些名称可能只出现一次或什至根本不出现,而一两个是频率高达 100 或更多。我还注意到一个由 8 个名字组成的块的模式,频率降低,然后又回来。

标签: mysql random null lookup multiple-results


【解决方案1】:

由于RAND() 不是确定性的,WHERE 条件每行计算/执行一次。因此,每一行有 1/199 的机会被选中。您可以在 FROM 子句(派生表)中使用子查询来精确生成一个随机数:

SELECT f.id, f.firstname
FROM firstname f
JOIN (SELECT floor(rand()*200)+1 as rnd) r ON r.rnd = f.id

【讨论】:

  • 谢谢你,保罗,你的代码就像一个魅力,我只是想确保我完全理解你在说什么?那么当查询运行时,WHERE 子句会在查找表中的每一行上运行吗?意思是,当它查看 id 1 并且随机生成器恰好是 1 时,它将把它添加到结果中,依此类推直到 200?
  • 是 - 对于每一行,在 WHERE 子句中生成一个新的随机数。这样一来,您就可以获得没有行、多行甚至(尽管不太可能)从 1 到 200 的所有行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多