随机唯一的Mysql Id

3
我有一个表格,想要使用1个MySQL查询生成随机唯一值并将其添加到表格中。 表格结构如下:
id | unique_id
1  | 1
2  | 5
3  | 2
4  | 7

等等

unique_id是无符号整数(10)

因此,我想每次用唯一的随机值(不是我的示例中的1、5、2、7)填写unique_id字段。

算法如下:

1. Get 1 unique random value, which will not have duplicates in unique_id field
2. Create new row with unique_id = result of 1 query

我尝试了。
SELECT FLOOR(RAND() * 9) AS random_number 
FROM table 
HAVING random_number NOT IN (SELECT unique_id FROM table) 
LIMIT 1

但它生成的值不是唯一的...
备注:乘数=9仅为示例,使用这样的乘数很容易重现这个问题。
2个回答

3

一种方法是使用 id 列,就像随机排列一样:

select id
from tables
order by rand()
limit 1

(您的示例仅返回一个值。)

为了为每个id返回可重复的随机数,您可以像这样做:

select id,
       (select count(*) from table t2 where rand(t2.id) < rand(t.id)) as randomnumber
from table t

这里所做的是通过生成随机数种子来产生稳定的排序顺序。这保证了唯一性,尽管这并不特别高效。
一个更高效的替代方法是使用变量:
SELECT  id, @curRow := @curRow + 1 AS random_number
FROM table CROSS JOIN (SELECT @curRow := 0) r
order by rand()

注意:此函数返回表的大小范围内的随机数字,不一定是从id中获取。这可能是件好事。
最后,您可以通过一个小技巧来实现您想要处理的想法。计算一个md5哈希值,然后将前四个字符强制转换为整数并在表中进行检查:
SELECT convert(hex(left(md5(rand()), 4)), unsigned) AS random_number 
FROM table 
HAVING random_number NOT IN (SELECT unique_id FROM table) 
LIMIT 1

您需要将值插入回表中。并且,不能保证您实际上能够获得不在表中的值,但对于数百万个值,它应该能够正常工作。


如果你需要多个id,或者所有的id,只需更改限制子句。你问题中的示例仅返回一个id。去掉限制并为每个id获取唯一的数字(从id集合中--这显然对于0-8的示例不起作用)。 - Gordon Linoff
为什么它们会是唯一的? 从表格中选择id 按随机顺序排序 限制1个 有时会返回重复项 - freento
@magalter,我明白了。你的示例由于限制只返回一行。一旦你有了稳定的排序顺序(如修订后的示例),你将得到唯一的结果。但是,如果你有大量数据,我建议使用临时表。 - Gordon Linoff
我会尝试解释我的目标。 我需要为新添加的记录生成一个随机唯一ID。id字段是自增的,因此不是随机的。unique_id需要是随机的。 因此,在添加新行之前,我需要执行SQL查询并获取1个随机且唯一的数字,以将其插入表中作为unique_id。 算法如下:
  1. 获取1个唯一的随机记录以用于新行
  2. 使用此记录创建新行
- freento
我稍微修改了我的问题,并添加了算法步骤。 - freento

0
如果您可以使用MD5哈希作为唯一ID,请选择MD5(NOW())。这几乎肯定会每次生成一个唯一的ID。
参考:MySQL论坛

unique_id 是整数字段。我需要百分之百确定 unique_id 是唯一的。 - freento
1
你尝试过增加 RAND() 函数的乘数吗?相对而言,随着这个池子的缩小,遇到现有标识符的可能性就越大。unique_id 字段的大小是否有任何限制? - Daniel Park
unique_id 是一个无符号的整数(10)。 我可以增加乘数,没有问题,但是结果数字仍然可能不唯一,有时会重复 :) 我需要真正独特的值,而且我没有容错的余地。 - freento
乘数为9仅作为示例,使用这样的乘数很容易重现此问题。 - freento
1
为确保唯一性,您可能需要增加一些复杂的操作。在其中添加一个IF测试以检查所有现有标识符将是必需的。 - Daniel Park
所以我需要一个能够做到这件事的好查询,我在请求它 :) 可能带有 IF 条件。 - freento

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接