【问题标题】:Generate unique random numbers using SQL使用 SQL 生成唯一的随机数
【发布时间】:2013-11-09 11:52:14
【问题描述】:

我有一些使用以下技术生成随机数的 SQL 代码:

DECLARE @Random1 INT, @Random2 INT, @Random3 INT, @Random4 INT, @Random5 INT, @Random6 INT, @Upper INT, @Lower INT
---- This will create a random number between 1 and 49
SET @Lower = 1 ---- The lowest random number
SET @Upper = 49; ---- The highest random number


with nums as (
    select @lower as n
    union all
    select nums.n+1
    from nums
    where nums.n < @Upper
   ),
   randnums as 
   (select nums.n, ROW_NUMBER() over (order by newid()) as seqnum
    from nums
   )
select @Random1 = MAX(case when rn.seqnum = 1 then rn.n end),
       @Random2 = MAX(case when rn.seqnum = 2 then rn.n end),
       @Random3 = MAX(case when rn.seqnum = 3 then rn.n end),
       @Random4 = MAX(case when rn.seqnum = 4 then rn.n end),
       @Random5 = MAX(case when rn.seqnum = 5 then rn.n end),
       @Random6 = MAX(case when rn.seqnum = 6 then rn.n end)
from randnums rn;

select @Random1, @Random2, @Random3, @Random4, @Random5, @Random6

我的问题是这个数字生成有多随机?还有另一种更“随机”的方法吗?

我正在使用:

Microsoft SQL Server 2008 (SP3) - 10.0.5512.0 (X64)   Aug 22 2012 19:25:47   Copyright (c) 1988-2008 Microsoft Corporation  Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) 

大多数解决方案的问题是你最终会得到这样的值:14,29,8,14,27,27我不能有重复的数字!

【问题讨论】:

  • 就像在您的 previous question 中一样,您可以使用 ORDER BY CRYPT_GEN_RANDOM(8) 来返回“加密随机数”
  • 您是对的,将之前的答案标记为您的解决方案,并在此处为您投票。如果您可以在此处的答案中解释代码的工作原理,请将您标记为勾选:)
  • 其实没有,因为你的方法仍然会导致欺骗出现:` 2,44,1,13,41,44`
  • 那里的答案不符合这里的要求,即6个数字之间不能重复。为此,您可以在此处获取现有查询并将对newid 的引用更改为使用CRYPT_GEN_RANDOM

标签: sql sql-server tsql


【解决方案1】:

我想你可以做这样的事情更简单,更容易

DECLARE @Upper INT;
DECLARE @Lower INT;
SET @Lower = 1;     /* -- The lowest random number */
SET @Upper = 49;    /* -- The highest random number */
    
    
SELECT @Lower + CONVERT(INT, (@Upper-@Lower+1)*RAND());

为了得到一个不重复的随机数,这样就可以了

WITH CTE 
AS
(
    SELECT  randomNumber, COUNT(1) countOfRandomNumber
    FROM (
    SELECT ABS(CAST(NEWID() AS binary(6)) %49) + 1 randomNumber
    FROM sysobjects
    ) sample
    GROUP BY randomNumber
)
SELECT TOP 5 randomNumber
FROM CTE
ORDER BY newid() 

要设置最高限额,您可以将 49 替换为您的最高限额。

【讨论】:

  • 不,因为我需要确保随机 1-6 中不会出现相同的数字
  • 这个问题是你最终会得到这样的值:14,29,8,14,27,27我不能有重复的数字!
  • @PriceCheaperton 看看我已经更新了我的答案,希望这能完成这项工作
  • 我不认为这比他们已经拥有的更“随机”。它仍然依赖于newid 的随机属性。
  • 只需为数字1-49 分配一个随机数并获得前6名(就像他们在OP中一样)就可以了。我认为这不会增加任何随机性。我怀疑newid 提供的随机性程度与CRYPT_GEN_RANDOM 等内置专用功能相比
【解决方案2】:

对于 Laravel

 public function generatUniqueId()
    {
        $rand = rand(10000, 99999);
        $itemId = $rand;
        while (true) {
            if (!BookItem::whereBookItemId($itemId)->exists()) {
                break;
            }
            $itemId = rand(10000, 99999);
        }

        return $itemId;
    }

【讨论】:

    【解决方案3】:
    1. 创建一个随机数列表。对于这个例子,我做了 100 个,可能更多,也可能更少(但不低于你的限制)

    2. 使用 row_number() 函数检测重复项

    3. 删除重复项后,选择列表中的前 6 个号码

       with RandomNumbers as
       (
           select id = 1, number = round(((56 - 1 -1) * RAND(CHECKSUM(NEWID())) + 1), 0),
           orderid = round(((56 - 1 -1) * RAND(CHECKSUM(NEWID())) + 1), 0)
           union all
           select id + 1, round(((56 - 1 -1) * RAND(CHECKSUM(NEWID())) + 1), 0), round(((56 - 1 -1) * RAND(CHECKSUM(NEWID())) + 1), 0) 
           from RandomNumbers where id < 100
       ), 
       NoDuplicates as
       (
           select number, id = row_number() over (partition by number orderid by order) from
           (
               select numeber, order, repeat = row_number() over (partition by numeber orderid by order)
               from RandomNumbers 
           ) a
           where repeat = 1
       )
      

      select * from NoDuplicates where id

    【讨论】:

      【解决方案4】:

      你可以使用 Rand() 函数。

      select CEILING(RAND() *<max of random numbers))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-27
        • 1970-01-01
        • 1970-01-01
        • 2018-05-03
        • 2014-05-26
        • 1970-01-01
        相关资源
        最近更新 更多