【问题标题】:Generate random int value from 3 to 6生成从 3 到 6 的随机 int 值
【发布时间】:2011-12-14 06:21:12
【问题描述】:

是否可以在 Microsoft SQL Server 中生成从 Min 到 Max 的随机 int 值(3-9 示例,15-99 等)

我知道,我可以生成从 0 到 Max,但是如何增加 Min 边界?

此查询生成从 1 到 6 的随机值。需要将其从 3 更改为 6。

SELECT table_name, 1.0 + floor(6 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

5 秒后添加

愚蠢的问题,对不起...

SELECT table_name, 3.0 + floor(4 * RAND(convert(varbinary, newid()))) magic_number 
FROM information_schema.tables

【问题讨论】:

  • 只有当您对表具有管理员类型权限时,您的答案才有效。我解决这个问题的方法是使用字段上的主键作为种子。分发并不出色,但它达到了目的。

标签: sql sql-server sql-server-2008


【解决方案1】:

一个有用的编辑器在每个语句之前添加了“选择”,但该项目的重点是它可以为返回中的每一行生成唯一键,而不仅仅是一个项目(为此,我将使用 Rand() 函数) . 例如: 从 tblExample 中选择前 100 个 Rand(),*

将为所有 100 行返回相同的随机值。

同时: 从 tblexample 中选择前 100 个 ABS(CHECKSUM(NEWID()) % 10),*

将在返回的每一行上返回 0 到 9 之间的不同随机值。 因此,虽然 select 使复制和粘贴变得更容易,但如果需要,您可以将逻辑复制到 select 语句中。

这会生成一个介于 0-9 之间的随机数

SELECT ABS(CHECKSUM(NEWID()) % 10)

1 到 6

SELECT ABS(CHECKSUM(NEWID()) % 6) + 1

3 到 6

SELECT ABS(CHECKSUM(NEWID()) % 4) + 3

动态(基于 Eilert Hjelmeseths 评论,已更新以修复错误(+ 到 -))

SELECT ABS(CHECKSUM(NEWID()) % (@max - @min - 1)) + @min

基于 cmets 更新:

  • NEWID 生成随机字符串(返回的每一行)
  • CHECKSUM 获取字符串的值并创建数字
  • 模数 (%) 除以该数字并返回余数(意味着最大值比您使用的数字小一)
  • ABS 将负面结果改为正面
  • 然后在结果中加一以消除 0 个结果(模拟掷骰子)

【讨论】:

  • 这对我帮助很大!请记住,如果您尝试为批量插入生成随机密钥,这可能会导致重复并且某些语句会失败。不过谢谢!
  • 如果我必须生成 1 到 27 之间的随机数怎么办?即范围大于 9?
  • 如果我遵循逻辑,似乎这个调整可以准确地让您轻松地动态设置范围。 ABS(CHECKSUM(NEWID()) % (@max - @min + 1)) + @min 。我的一些测试产生了很好的结果。如果它确实准确,我认为可以通过包含它来稍微改进这个答案。
【解决方案2】:

一般:

select rand()*(@upper-@lower)+@lower;

对于您的问题:

select rand()*(6-3)+3;

select rand()*3+3;

【讨论】:

    【解决方案3】:

    这是简单而单行的代码

    为此,请使用 SQL Inbuild RAND() 函数。

    这是在两个数字之间生成随机数的公式(RETURN INT Range)

    这里 a 是您的第一个数字(最小值),b 是范围内的第二个数字(最大值)

    SELECT FLOOR(RAND()*(b-a)+a)
    

    注意:您也可以使用 CAST 或 CONVERT 函数来获取 INT 范围号。

    ( CAST(RAND()*(25-10)+10 AS INT) )

    例子:

    SELECT FLOOR(RAND()*(25-10)+10);
    

    这是在两个数字之间生成随机数的公式(返回十进制范围)

    SELECT RAND()*(b-a)+a;
    

    例子:

    SELECT RAND()*(25-10)+10;
    

    更多详情请查看:https://www.techonthenet.com/sql_server/functions/rand.php

    【讨论】:

    • 注意,如链接文章中所述,这实际上不会生成值 = Max。例如,对于 >= 10 和
    【解决方案4】:

    简单地说:

    DECLARE @MIN INT=3; --We define minimum value, it can be generated.
    DECLARE @MAX INT=6; --We define maximum value, it can be generated.
    
    SELECT @MIN+FLOOR((@MAX-@MIN+1)*RAND(CONVERT(VARBINARY,NEWID()))); --And then this T-SQL snippet generates an integer between minimum and maximum integer values.
    

    您可以根据需要更改和编辑此代码。

    【讨论】:

    • 虽然欢迎使用此代码 sn-p,并且可能会提供一些帮助,但它会是 greatly improved if it included an explanation of 如何解决这个问题。没有它,你的答案就没有多大的教育价值了——记住你是在为将来的读者回答这个问题,而不仅仅是现在问的人!请edit您的答案添加解释,并说明适用的限制和假设。
    【解决方案5】:
    DECLARE @min INT = 3;
    DECLARE @max INT = 6;
    SELECT @min + ROUND(RAND() * (@max - @min), 0);
    

    一步一步

    DECLARE @min INT = 3;
    DECLARE @max INT = 6;
    
    DECLARE @rand DECIMAL(19,4) = RAND();
    DECLARE @difference INT = @max - @min;
    DECLARE @chunk INT = ROUND(@rand * @difference, 0);
    DECLARE @result INT = @min + @chunk; 
    SELECT @result;
    

    请注意,用户定义的函数因此不允许使用 RAND()。解决方法(来源:http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/)是先创建一个视图。

    CREATE VIEW [dbo].[vw_RandomSeed]
    AS
    SELECT        RAND() AS seed
    

    然后创建随机函数

    CREATE FUNCTION udf_RandomNumberBetween
    (
        @min INT,
        @max INT
    )
    RETURNS INT
    AS
    BEGIN
        RETURN @min + ROUND((SELECT TOP 1 seed FROM vw_RandomSeed) * (@max - @min), 0);
    END
    

    【讨论】:

      【解决方案6】:

      Lamak 的答案作为函数:

      -- Create RANDBETWEEN function
      -- Usage: SELECT dbo.RANDBETWEEN(0,9,RAND(CHECKSUM(NEWID())))
      CREATE FUNCTION dbo.RANDBETWEEN(@minval TINYINT, @maxval TINYINT, @random NUMERIC(18,10))
      RETURNS TINYINT
      AS
      BEGIN
        RETURN (SELECT CAST(((@maxval + 1) - @minval) * @random + @minval AS TINYINT))
      END
      GO
      

      【讨论】:

        【解决方案7】:

        漂亮而简单,来自 Pinal Dave 的网站:

        http://blog.sqlauthority.com/2007/04/29/sql-server-random-number-generator-script-sql-query/

        DECLARE @Random INT;
        DECLARE @Upper INT;
        DECLARE @Lower INT
        SET @Lower = 3 ---- The lowest random number
        SET @Upper = 7 ---- One more than the highest random number
        SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
        SELECT @Random
        

        (我确实对@Upper- 做了些许改动,以包含大数字,加了 1。)

        【讨论】:

        • 我在另一个帖子中看到了这个例子。它不提供随机分布。例如,Lower 是 1,Upper 是 11,所以我想要从 1 到 10 的随机数。1 和 10 的出现次数为 2-8。去测试一下。
        【解决方案8】:
        SELECT ROUND((6 - 3 * RAND()), 0)
        

        【讨论】:

        • 获得一个数字而不是另一个数字的机会并不是平均分布的。检查这个的输出:SELECT ROUND((6 - 3 * 0.16), 0) SELECT ROUND((6 - 3 * 0.17), 0) SELECT ROUND((6 - 3 * 0.5), 0) SELECT ROUND((6 - 3 * 0.51), 0) SELECT ROUND((6 - 3 * 0.83), 0) SELECT ROUND((6 - 3 * 0.84), 0) 显示 16% 变化为 6,~34% 为 5,~34% 为 4,~16% 为 3。
        • 截断优于舍入
        【解决方案9】:

        我看到您在 SQL Server 2008 中添加了对您的问题的答案,您也可以这样做

        SELECT 3 + CRYPT_GEN_RANDOM(1) % 4 /*Random number between 3 and 6*/ 
        FROM ...
        

        这种方法的几个缺点是

        1. 这比NEWID()方法慢
        2. 即使每行计算一次,查询优化器也没有意识到这一点can lead to odd results

        但我只是想我会添加它作为另一个选项。

        【讨论】:

        • @FSou1 - 是的。我认为CRYPT_GEN_RANDOM 确实适用于您需要更安全的伪随机数的情况。
        【解决方案10】:

        你可以这样做:

        DECLARE @maxval TINYINT, @minval TINYINT
        select @maxval=24,@minval=5
        
        SELECT CAST(((@maxval + 1) - @minval) *
            RAND(CHECKSUM(NEWID())) + @minval AS TINYINT)
        

        那是直接取自this link,我真的不知道如何正确评价这个答案。

        【讨论】:

          猜你喜欢
          • 2012-03-10
          • 2014-05-21
          • 2011-09-07
          • 2020-06-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多