【问题标题】:Pulling a random value out of a table is returning a null value从表中拉出一个随机值会返回一个空值
【发布时间】:2021-01-10 03:10:07
【问题描述】:

我有一个存储过程,当我想在测试环境中使用它时,我用它来“去识别”客户端信息。我正在用随机值替换实际名称和地址。我在一个名为 dict(用于字典)的数据库中有用于女性姓名、男性姓名、姓氏和地址的数据库表。

其中每一个都有一个名为 f_row_id 的字段,它是从 1 到 x 的序列号,对应表中的每条记录。

我们最近升级到 mySQL 8 并且存储过程停止工作。对于我尝试从另一个表中填充随机值的每个字段,我最终都得到了 NULL。在尝试查找现在可以使用的方法时,我无法让以下查询按预期工作:

SELECT
    f_enroll_id,
    (SELECT f_name FROM dict.dummy_female_first_name fn WHERE fn.f_row_id = (FLOOR(RAND() * 850)  + 1) LIMIT 1)
FROM
    t_enroll

我的数据表(我最终希望包含随机名称)称为 t_enroll。在那个 (f_enroll_id) 中有一个 ID 字段,我想获取每个 ID 的列表以及该表中每条记录的随机名字。

随机名字表 (dummy_female_first_name) 中有 850 条记录(在我的存储过程中,这是我在过程开始时计算的会话变量)。

当我第一次尝试运行它时,我收到一个错误,即我的子查询返回了多个值。我不明白为什么会这样做,因为 (FLOOR(RAND() * 850) + 1) 应该返回一个整数。所以我添加了 LIMIT 1。但是当我运行它时,大约一半的返回行的名字为 NULL。

我已验证我的名字表中的所有行都有一个行 ID,行 ID 是唯一的,并且数字中没有任何间隙。

你认为这是什么原因造成的?

提前致谢!

这是我正在更新的表的架构:

CREATE TABLE `t_enroll` (
  `f_enroll_id` int(15) NOT NULL AUTO_INCREMENT,
  `f_status` int(2) DEFAULT NULL,
  `f_date_enrolled` date NOT NULL DEFAULT '0000-00-00',
  `f_first_name` varchar(20) DEFAULT NULL,
  `f_mi` char(1) DEFAULT NULL,
  `f_last_name` varchar(20) NOT NULL DEFAULT '',
  `f_maiden_name` varchar(20) DEFAULT NULL,
  `f_dob` date NOT NULL DEFAULT '0000-00-00',
  `f_date_fee_received` date NOT NULL DEFAULT '0000-00-00',
  `f_gender` int(11) NOT NULL DEFAULT '2',
  `f_address_1` varchar(40) DEFAULT NULL,
  `f_address_2` varchar(20) DEFAULT NULL,
  `f_quadrant` char(2) DEFAULT NULL,
  `f_city` varchar(25) DEFAULT NULL,
  `f_state` char(2) NOT NULL DEFAULT '',
  `f_county` varchar(3) NOT NULL,
  `f_zip_code` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`f_enroll_id`),
  KEY `f_date_enrolled` (`f_date_enrolled`),
  KEY `f_last_name` (`f_last_name`),
  KEY `f_first_name` (`f_first_name`),
  KEY `f_dob` (`f_dob`),
  KEY `f_gender` (`f_gender`)
ENGINE=InnoDB AUTO_INCREMENT=532 DEFAULT CHARSET=latin1 COMMENT='InnoDB free: 15360 kB';

这是我从中提取名称的字典表的架构:

CREATE TABLE `dummy_female_first_name` (
  `f_row_id` int(11) NOT NULL,
  `f_name` varchar(25) NOT NULL,
  PRIMARY KEY (`f_row_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

正如我在评论中提到的,我找到了一种使用 ORDER BY RAND() LIMIT 1 变体的替代方法。但我仍然很好奇是什么阻止了我原来的方法失败。这在最近的 mySQL 版本中有所改变,因为它曾经可以工作。

再次感谢。

【问题讨论】:

  • 请显示您的架构(show create table dict.dummy_female_first_nameshow create table t_enroll 的输出)和重现问题的示例数据
  • 显然我仍在学习在这里发帖,因为我不确定如何提供我的架构。当我尝试将其添加为评论时,它说我的评论太长了。我应该在多个小 cmets 中发布架构吗?
  • 顺便说一句,我找到了解决它的方法。如果我更改: (SELECT f_name FROM dict.dummy_female_first_name fn WHERE fn.f_row_id = (FLOOR(RAND() * 850) + 1) LIMIT 1) 到 (SELECT f_name FROM dict.dummy_female_first_name fn ORDER BY RAND() LIMIT 1) 它工作。
  • 不,只需编辑您的问题并添加即可。 cmets对于代码或sql不是很有用

标签: mysql sql random


【解决方案1】:

这是一种更昂贵的方法,但您可以使用:

SELECT f_enroll_id,
        (SELECT f_name FROM dict.dummy_female_first_name fn ORDER BY rand() LIMIT 1)
FROM t_enroll;

您可以使用以下方法提高效率:

SELECT f_enroll_id,
        (SELECT f_name
         FROM dict.dummy_female_first_name fn 
         WHERE rand() < 0.01
         ORDER BY rand() LIMIT 1
        )
FROM t_enroll;

where 子句意味着大约 8 行将被过滤,因此排序会快得多。

【讨论】:

    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 2021-12-03
    • 2014-02-11
    • 2021-12-05
    • 2011-07-29
    相关资源
    最近更新 更多