代码之家  ›  专栏  ›  技术社区  ›  MatBailie

这是为每条记录生成随机数的好方法还是坏方法?

  •  0
  • MatBailie  · 技术社区  · 15 年前

    我的一位同事在SQL Server中发现了一种我不知道的行为。

    CREATE VIEW dbo.vRandNumber AS
    SELECT RAND() as RandNumber
    GO
    
    CREATE FUNCTION dbo.RandNumber() RETURNS float AS
    RETURN (SELECT RandNumber FROM vRandNumber)
    GO
    
    DECLARE @mytable TABLE (id INT)
    INSERT INTO @mytable SELECT 1
    INSERT INTO @mytable SELECT 2
    INSERT INTO @mytable SELECT 3
    
    SELECT *, dbo.RandNumber() FROM @mytable
    

    似乎 是为数据集中的每条记录生成“随机”值的最快方法。但我不完全确定这是否是记录在案的行为的结果,或是利用了巧合的奇异巧合。

    用这样的东西?


    这不是关于RAND()函数本身优点的问题,而是使用UDF/视图组合强制它在每一行上重新计算的问题。(在最终查询中使用RAND()而不是dbo.RandNumber(),将为每个记录提供相同的值。)

    另外,问题是每次查看时,值都会有所不同。例如,允许随机选择记录。

    编辑

    5 回复  |  直到 15 年前
        1
  •  3
  •   Shannon Severance    15 年前

    如果我想继续开发SQL Server未来版本的软件,我不会这样做。我找到了一种方法,可以从RAND()中为select语句中的每一行返回不同的值。这一发现1)有点骇人,2)是在SQLServer2005上发现的。它不再适用于SQL Server 2008。这种经历让我更加了解了如何依靠诡计让rand()每行返回一个随机值。

    另外,我相信SQL Server可以优化对UDF的多次调用。。。尽管这可能正在改变,因为现在它们确实允许一些非确定性函数。

    仅限SQL Server 2005,强制在select语句中每行执行rand()的一种方法。 未在2005年之前的任何版本上测试:

    create table #t (i int)
    insert into #t values (1)
    insert into #t values (2)
    insert into #t values (3)
    
    select i, case when i = 1 then rand() else rand() end as r
    from #t
    
    1   0.84923391682467
    2   0.0482397143838935
    3   0.939738172108974
    

    另外,我知道你说你不是在问rand()的随机性,但我想一个很好的参考是: http://msdn.microsoft.com/en-us/library/aa175776(SQL.80).aspx

        2
  •  1
  •   Frank V    15 年前

    这取决于你需要什么样的随机值。它还取决于需要值的格式 INTEGER , VARCHAR

    SELECT *
    FROM [MyTable]
    ORDER BY newID()
    

    同样,您可以生成一个 ints

    newid()

    所以我回到 视情况而定。 你能详细说明你需要什么吗?

    :这是我的同事曾经让计算列在每次查询表时每行返回不同的随机数的表定义片段:

    CREATE TABLE [dbo].[Table](
        -- ...
        [OrderID] [smallint] NOT NULL,  --Not sure what happens if this is null
        -- ...
        [RandomizeID]  AS (convert(int,(1000 * rand(([OrderID] * 100 * datepart(millisecond,getdate())))))),
        -- ...
    )
    
        3
  •  0
  •   Justin Niessner    15 年前

    RAND() 正在生成真正的随机数。。。

        4
  •  0
  •   Maximilian Mayerl    15 年前

    我不会用这个。据我所知,RAND()使用系统时间作为种子,并在一次又一次快速执行时生成相同的值。例如,尝试以下方法:

    SELECT    *, 
              RAND()
    FROM      SomeTable
    

    RAND()将为每行提供相同的值。

        5
  •  0
  •   gbn    15 年前

    我会用 CHECKSUM(NEWID()) 生成一个随机数(而不是 RAND() * xxx CRYPT_GEN_RANDOM