2012-07-27 102 views
22

我想生成一个5位数的数字,它不会在数据库中重复。 假设我有一个名为numbers_mst的表,其字段名为my_number如何在不使用PHP的数据库中重复生成随机数?

我想生成的数字,它不会在这个my_number字段中重复的方式。 前面的零是允许在这个。所以00001等数字是允许的。 另一件事是它应该在00001到99999之间。我该怎么做?

我可以猜到的一件事是我可能不得不创建一个递归函数来检查数字到表中并生成。

+0

如果前面的零是允许的,它们是强制性的吗? 01与001不同? – ChrisW 2012-07-27 00:43:40

+0

我需要5位数字,或者你可以只说5位数字符串。所以01或001没有机会来:) – aslamdoctor 2012-07-27 00:51:17

+0

当你用完独特的数字时会发生什么? ;) – 2012-07-27 01:10:01

回答

37
SELECT FLOOR(RAND() * 99999) AS random_num 
FROM numbers_mst 
WHERE "random_num" NOT IN (SELECT my_number FROM numbers_mst) 
LIMIT 1 

此作用:

  1. 选择0之间的随机数 - 使用RAND()1。
  2. 将其放大为0至99999之间的数字。
  3. 仅选择表中尚不存在的那些。
  4. 只返回1个结果。
+1

这看起来不像有效的sql。是吗? – iWantSimpleLife 2012-07-27 00:53:55

+3

这是有效的和天才的答案。我正在等待完成2分钟的限制来接受这个答案lolz :) – aslamdoctor 2012-07-27 00:55:24

+1

如果数字表格填写不好,那么这样做很可能会失败。 – 2012-07-27 00:58:14

2
  1. 生成随机数。

  2. 检查随机数是否在数据库中。

  3. 如果没有,请停止使用此号码。

  4. 转到步骤1。

2

你有两种方法:

第一,在其他答案建议,是创建一个随机数(使用mt_rand()),并检查它不是在数据库中。如果它在数据库中,请重新登录并重试。这是最简单的,如果你正在生成一个单一的号码 - 请参阅代码的其他答案。但是,如果你发现50%的数字会变得非常缓慢和低效。

如果你想要很多数字,另一种方法是使用所有记录填充一个数据库,并选择一列。运行一个查询来查找有多少“未采摘”,然后找到0到“未采摘”之间的随机数。然后运行SQL查询以获取该位置的数字(未选中的位置,在MySQL中使用LIMIT)并将其标记为摘取。有点令人费解,如果你只需要几个数字,效率会更高,效率也更低,但当你想获得更多的数字时,效果会更好。

注意:您可以通过存储本地选择的计数并运行少量查询来提高效率。

+0

您可以通过从表中删除记录来优化第二个。因此,预先填充一个有连续数字的表格,然后在随机选取它们时简单地删除它们。 – 2012-11-24 11:33:32

+0

的确如此。但是,我经常会发现我需要记录哪个用户选择了哪个号码,哪个广告系列或哪个日期等等。 (我坚信保持日志/可追踪性/跟踪一切,这意味着很少删除任何东西,但通常会添加。对于随机抽签(我居住在哪里)这是一个法律要求,取决于工作。) – Robbie 2012-11-24 11:40:54

8

除了图莎尔的回答,使当numbers_mst是空的它的工作:

SELECT random_num 
FROM (
    SELECT FLOOR(RAND() * 99999) AS random_num 
    UNION 
    SELECT FLOOR(RAND() * 99999) AS random_num 
) AS numbers_mst_plus_1 
WHERE `random_num` NOT IN (SELECT my_number FROM numbers_mst) 
LIMIT 1 
+1

认真?两年半之后? – Areks 2014-12-03 14:17:43

+4

我想要更多这些:http://stackoverflow.com/help/badges/17/necromancer?userid=386718 – 2014-12-03 14:32:23

+0

让我检查我自己的徽章我有一个太大声笑,谢谢你的答案。 – Sam 2015-07-17 10:09:51

3

这是建立一个没有检查数据库中是唯一的代码生成最简单的方法,这将节省数据库查询执行时间。

function unique_code_generator($prefix='',$post_fix='') 
    { 
     $t=time(); 
     return (rand(000,111).$prefix.$t.$post_fix); 
    } 

享受,一个漂亮的编码一天有..

:)

+1

我喜欢这个,这很简单,但是在111中有一个机会,如果两个用户做到这一点,它会失败在同一时间,所以你可能想增加随机数。 :) – Niclas 2016-11-04 11:22:38

+0

是的,我同意你的看法。 – Roni 2016-11-05 05:27:07

+0

日光节约问题会发生什么? – 2017-11-01 08:46:12

1

注:其他发布将只如果列被配置为NOT NULL解决方案。如果NULL,它只会返回没有结果。您可以修复这样的查询:

SELECT random_num 
FROM (
    SELECT FLOOR(RAND() * 99999) AS random_num 
) AS numbers_mst_plus_1 
WHERE random_num NOT IN (SELECT my_number FROM numbers_mst WHERE my_number IS NOT NULL) 
LIMIT 1 

...的...WHERE my_number IS NOT NULL是必要的!

编辑:我只是想提一提,我故意删除内SELECT的表名,因为它没有必要的攻方,似乎打破,如果有表中没有任何数据了吗?但是,也许这是故意包含的? - 请为每个人澄清或评论,谢谢。

+2

你的工作很好,能够实际抓住一个未使用的随机数。但是,尝试一个小的数据集。如果选择的兰德不存在,则不返回任何结果 – jimbob 2017-08-29 09:18:46

0

我知道我的答案是晚了,但如果有人正在寻找这个问题在未来,谁也不会带前导零的随机数,你应该添加LPAD()功能。

所以您的查询就会喜欢

SELECT LPAD(FLOOR(RAND()*99999),5,0) 

有一个愉快的一天。

0

如下因素查询生成所有从0到99999 INT,发现未在目标表和这些免费号码随机地输出一个所使用的值:

SELECT random_num FROM (
    select a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a) as random_num 
    from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a 
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b 
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c 
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d 
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as e 
) q 
WHERE random_num NOT IN(SELECT my_number FROM numbers_mst) 
ORDER BY RAND() LIMIT 1 

好了,它是长期,缓慢和不可扩展,但它作为一个独立的查询!您可以添加删除更多“0”(联接a,b,c,d,e)以增加或减少范围。

您也可以使用这种发电机行技术与例如所有日期创建行。