【问题标题】:Random Number on SQL without using NewID()不使用 NewID() 的 SQL 上的随机数
【发布时间】:2011-01-15 21:28:53
【问题描述】:

您好,我想使用以下语句生成一个唯一随机数:

Convert(int, (CHECKSUM(NEWID()))*100000) AS [ITEM] 

因为当我在“from”上使用连接子句时,它会使用 NEWID() 生成双寄存器

我使用的是 SQL Server 2000

*PD:当我使用 Rand() 时,它可能会以 100000000 的概率 1 重复,但这非常关键,因此重复生成随机值的概率必须为 0%

我的 NewID() 查询和 SELECT 语句的结果重复 (x2) 我没有 NewID() 并在 SELECT 语句上使用 Rand() 的查询是单个 (x1) 但重复生成的随机值的概率不确定但存在!

谢谢!

【问题讨论】:

  • 什么数据库?甲骨文?微软SQL? MySQL? PostgreSQL?许多数据库已经有了随机函数。
  • 有什么问题?标志?没有浮点数?溢出?我们也使用 NEWID() 是有原因的:它可能是最好的解决方案
  • @Angel Escobedo,当我运行您的命令时:select Convert(int, (CHECKSUM(NEWID()))*100000) AS [ITEM] 我得到:消息 8115,级别 16,状态 2,第 1 行将表达式转换为数据类型 int 的算术溢出错误。
  • 我不能使用 NEWID() 因为当我使用 Join 时,如果我在 SELECT 语句上使用 Distinct 也会产生重复
  • @KM select Convert(int, RAND(CHECKSUM(NEWID()))*10000) AS [ITEM] = 8114 for me SQL Server 8.0 (20000) SP 4

标签: sql sql-server tsql random


【解决方案1】:

在 SQL Server 中,您可以使用它来生成随机数,或指定参数之间的随机整数

DECLARE @RandomNumber float
DECLARE @RandomInteger int
DECLARE @MaxValue int
DECLARE @MinValue int

SET @MaxValue = 4
SET @MinValue = 2

SELECT @RandomNumber = RAND()

SELECT @RandomInteger = ((@MaxValue + 1) - @MinValue) * @RandomNumber + @MinValue

SELECT @RandomNumber as RandomNumber, @RandomInteger as RandomInteger

【讨论】:

  • 我认为这不会导致“唯一随机数”
【解决方案2】:

如果您使用的是 MySQL

 SELECT RAND();

MySQL 文档: http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_rand

如果您使用的是 Postgres

SELECT RANDOM();

Postgres 文档: http://www.postgresql.org/docs/8.0/static/functions-math.html

【讨论】:

    【解决方案3】:

    【讨论】:

      【解决方案4】:

      溢出了吗?

      CAST(CHECKSUM(NEWID()) AS bigint) * CAST(100000 AS bigint) AS [ITEM]
      
      CAST(CAST(CHECKSUM(NEWID()) AS bigint) * CAST(100000 AS bigint) % 2100000000 AS int) AS [ITEM]
      

      编辑:

      没有0%的机会重复号码

      CHECKSUM(NEWID())) 返回一个整数,它有 40 亿行。 birthday paradox 意味着碰撞的机会当然要高得多。

      Bigint(上图)或小数(38,0)给你更多的发挥空间,但只会减少碰撞的机会,但永远不会消除。

      但仍然不明白你为什么要尝试加入一个唯一的随机数...

      【讨论】:

      • 您好如何像 UINT 一样将其转换为正数?
      【解决方案5】:

      用一位数更新列

      update  [dbo].[AccomodationRatings]
      set Rate =rand(CHECKSUM(NEWID()))*10
      WHERE Rate >0
      

      【讨论】:

        【解决方案6】:

        好的,所以首先如果你不想使用“NEWID”函数来生成随机数,那么你可以使用“RAND”函数,这样的东西会是随机的:

        SELECT CAST(ROUND((RAND() - .5) * 2147483647, 0) AS INT)
        

        如果您需要 BIGINT,请将其转换为 BIGINT,但请记住,它只会为您提供 INT 的熵(和范围):

        SELECT CAST(ROUND((RAND() - .5) * 2147483647, 0) AS BIGINT)
        

        所有这些其他答案都返回 BIGINT,因为我建议使用“NEWID”函数,但我会这样做不同。例如,如果您使用一个“CHECKSUM(NEWID()) AS bigint)”然后返回一个 BIGINT 的任何变体,那么您只有一个 INT 的熵,而不是一个 BIGINT,而是尝试使用两个:

        SELECT CAST(CAST(CHECKSUM(NEWID()) AS BINARY(4)) + CAST(CHECKSUM(NEWID()) AS BINARY(4)) AS BIGINT)
        

        我想如果你真的不喜欢“NEWID”功能,你也可以用“RAND”来做到这一点:

        SELECT CAST(CAST(ROUND((RAND() - .5) * 2147483647, 0) AS BINARY(4)) + CAST(ROUND((RAND() - .5) * 2147483647, 0) AS BINARY(4)) AS BIGINT)
        

        现在应该(或多或少)为您提供 BIGINT 的熵,当然它可能并不完美,而且我还没有证明它是否会产生均匀分布,因此请谨慎使用。

        确实,如果您想确保给定 ID 是唯一的,则需要使用 GUID 或 GUID 等效项,如果您生成的值不在该范围内,则必须这样做,或者在单独的表中跟踪生成的字段/在创建 ID 之前扫描表。没有办法解决这个问题。此外,您不能以 0% 的碰撞几率以随机方式生成两个独立值。你可以接近perfectly safe though.

        注意:对于那些不怕使用 NEWID 的人)我会执行以下操作,以最少的体操获得完整的 16 个字节的熵:

        SELECT CAST(CAST(NEWID() AS VARBINARY(8)) AS BIGINT) 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-05
          • 1970-01-01
          • 1970-01-01
          • 2015-04-26
          相关资源
          最近更新 更多