如何在TSQL Select中为每一行生成随机数?
我需要一个不同的随机数字用于表格中的每一行。 以下看似明显的代码为每一行使用相同的随机值。
SELECT table_name, RAND() magic_number
FROM information_schema.tables
我想要一个INT或FLOAT出来。 故事的其余部分是我将使用随机数字来创建一个从知道日期的随机日期偏移量,例如从开始日期偏移1到14天。
这是针对Microsoft SQL Server 2000的。
看看SQL Server - 基于随机数的设置,它有一个非常详细的解释。
总而言之,下面的代码会生成一个介于0和13之间的随机数,并带有规范化的分布:
ABS(CHECKSUM(NewId())) % 14
要更改范围,只需更改表达式末尾的数字即可。 如果您需要包含正数和负数的范围,请特别小心。 如果你做错了,可以对数字0进行重复计数。
对房间内数学坚果的一个小警告:这个代码有一个很小的偏见。 CHECKSUM()
产生的数字在sql Int数据类型的整个范围内是统一的,或者至少在我的(编辑器)测试可以显示的范围内。 但是,当CHECKSUM()在该范围的最高端产生一个数字时,会有一些偏差。 任何时候,如果在最大整数之前得到最大可能整数和所需范围大小(本例中为14)的最后一个精确倍数之间的数字,那么这些结果对于范围中不能从那是14的倍数。
举一个例子,想象一下Int类型的整个范围只有19个。19是您可以容纳的最大可能整数。 当CHECKSUM()结果在14-19时,这些结果与结果0-5相对应。 这些数字将在6-13之间受到很大的青睐,因为CHECKSUM()产生它们的可能性是其两倍。 视觉上更容易证明这一点。 以下是我们假想整数范围的全部可能结果集合:
Checksum Integer: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Range Result: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 0 1 2 3 4 5
你可以在这里看到,产生一些数字的机会比其他人多:偏见。 值得庆幸的是,Int类型的实际范围要大得多......以至于在大多数情况下,偏差几乎检测不到。 但是,如果您发现自己正在为严肃的安全代码执行此操作,则需要注意这一点。
当在单个批次中多次调用时,rand()返回相同的数字。
我建议使用convert( varbinary
, newid()
)作为种子参数:
SELECT table_name, 1.0 + floor(14 * RAND(convert(varbinary, newid()))) magic_number
FROM information_schema.tables
newid()
保证每次调用时都会返回一个不同的值,即使在同一个批处理中也是如此,所以使用它作为种子会提示rand()每次给出不同的值。
编辑从1到14得到一个随机的整数。
RAND(CHECKSUM(NEWID()))
以上将生成一个0到1之间的(伪)随机数,是唯一的。 如果在select中使用,因为种子值为每一行更改,它将为每一行生成一个新的随机数(但不保证每行生成一个唯一的数字)。
结合上限10时的示例(产生数字1 - 10):
CAST(RAND(CHECKSUM(NEWID())) * 10 as INT) + 1
Transact-SQL文档:
CAST()
:https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql RAND()
:http://msdn.microsoft.com/en-us/library/ms177610.aspx CHECKSUM()
:http://msdn.microsoft.com/en-us/library/ms189788.aspx NEWID()
:https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql 上一篇: How do I generate random number for each row in a TSQL Select?