代码之家  ›  专栏  ›  技术社区  ›  Mark Ransom

在MS SQL Server 2005中使用rand()时,我做错了什么?

  •  3
  • Mark Ransom  · 技术社区  · 16 年前

    我想从一张小桌子上随机抽取10%的样本。我想我只需要使用rand()函数并选择那些随机数小于0.10的行:

    SELECT * FROM SomeTable
    WHERE SomeColumn='SomeCondition' AND
          RAND() < 0.10
    

    但我很快发现rand()总是返回相同的数字!让我想起这个 xkcd cartoon .

    好的,没问题,rand函数接受一个seed值。我将定期运行此查询,如果在不同的日期运行它,我希望它给出不同的结果,因此我将使用日期和唯一行ID的组合对其进行种子设定:

    SELECT * FROM SomeTable
    WHERE SomeColumn='SomeCondition' AND
          RAND(CAST(GETDATE) AS INTEGER) + RowID) < 0.10
    

    我还是没有任何结果!当我显示兰德返回的随机数时,我发现它们都在一个很窄的范围内。从rand中获取随机数似乎需要使用随机种子。如果我有一个随机种子,我就不需要一个随机数!

    我已经看过与此问题相关的以前讨论:

    SQL Server Random Sort
    How to request a random row in SQL?

    他们帮不了我。tablesample在页面级别工作,这对大表很好,但对小表不好,而且它看起来像是在WHERE子句之前应用的。带newid的top不起作用,因为我不知道提前需要多少行。

    有人有解决方案,或者至少有提示吗?

    编辑: 感谢Alexcuse solution 它适用于我的特定案例。现在,更大的问题是,如何使兰德行为?

    5 回复  |  直到 7 年前
        1
  •  6
  •   AlexCuse    16 年前

    这种方法(以_表示)不能保证10%的抽样率。它只会给您所有的行,其中rand()的计算结果为<.10,这将不一致。

    类似的东西

    select top 10 percent * from MyTable order by NEWID()
    

    会成功的。

    编辑: 没有真正的好方法让兰德表现出来。这是我过去使用过的(kludge alert-它会杀死你无法在UDF中使用rand())。

    CREATE VIEW RandView AS 
    
    SELECT RAND() AS Val
    
    GO
    
    CREATE FUNCTION RandomFloat()
    RETURNS FLOAT
    AS
    BEGIN
    
    RETURN (SELECT Val FROM RandView)
    
    END
    

    那你就有了 select blah, dbo.RandomFloat() from table 在你的询问中。

        2
  •  2
  •   Peter O. Manuel Pinto    7 年前

    如果您的表有一列(甚至 罗维德 列)一般来说是数字,如整数、浮点或SQL数值,请尝试以下操作:

    SELECT * FROM SomeTable WHERE SomeColumn='SomeCondition' AND 0*rowid+RAND() < 0.10
    

    为了评估 RAND() 一次 每行 ,一次也不 查询的开始 .

    这应该归咎于查询优化器。也许还有别的办法,但我相信这对你有用。

        3
  •  1
  •   Jason DeFontes    16 年前

    这似乎有效:

    select * from SomeTable
    where rand(0*SomeTableID + cast(cast(newid() as binary(4)) as int)) <= 0.10
    
        4
  •  0
  •   Community Anvaka    7 年前

    你看到这个问题了吗?

    How do I return random numbers as a column in SQL Server 2005?

    Adam发布了一个UDF,你可以用它来代替Rand(),效果更好。

        5
  •  0
  •   Amarnath Balasubramanian    11 年前

    这个好像管用

    SELECT TOP 10 PERCENT * FROM schema.MyTable ORDER BY NEWID()