kak*_*sat 10 t-sql sql-server random random-seed
我想从均匀分布中生成随机值,其中对于T-SQL中给定数据表的每一行,mean = 0和标准devation = 1.另外,我想设置种子以确保分析的可重复性.以下是不起作用的想法:
使用RAND()具有声明数字的函数不能实现此目标:为数据集的每一行生成相同的随机值.
这样的解决方案:
SELECT ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]
由于它不可再现,因此无法解决问题.
编辑:
由于我的表有数亿条记录,因此性能很重要.
Rand() 函数可以在开始时通过向其传递一个整数种子值来进行播种。如果在生成任何随机数之前执行此操作一次,则随机数序列将是可重复的。单独生成值将确保 Rand() 函数按顺序返回数字。以下将产生n 个伪随机数的均匀分布,平均值 = 0,标准差 = 1:
DECLARE @Mean FLOAT = 0.0;
DECLARE @stDev FLOAT = 1.0;
DECLARE @n INT = 100000; -- count of random numbers to generate
DECLARE @U TABLE(x FLOAT); -- table of random numbers
DECLARE @SEED INT = 123456; -- seed to ensure list is reproducible
SELECT RAND(@Seed);
SET NOCOUNT ON;
BEGIN TRAN
DECLARE @x INT = 0; -- counter
WHILE @x < @n
BEGIN
INSERT INTO @U (x)
SELECT @Mean + (2 * SQRT(3) * @stDev) * (RAND() - 0.5)
SET @x = @x + 1;
END;
COMMIT
-- Check the results
SELECT * from @U;
SELECT AVG([@U].x) AS mean,
STDEV([@U].x) AS stDev
FROM @U;
Run Code Online (Sandbox Code Playgroud)
您可以使用游标循环遍历现有表中的记录并对每条记录执行更新,而不是在 while 循环中插入临时表。正如评论中提到的,性能可能是一个问题,但它满足“均值 = 0 且标准差 = 1 的均匀分布”和“再现性”的要求。Rand() 函数的工作方式强制进行“1 by 1”更新。
下面是一个替代 Rand() 函数的替代方案,它具有更好的性能(应该在 2 秒内运行 100 万行)。这允许在单个记录中更新记录UPDATE,但依赖于ID表中的唯一数字字段并更新名为 的字段RandomNumber。Rand() 函数被替换为( (ID * @SEED ) % 1000 ) / 1000可能可以改进的函数。
DECLARE @Mean FLOAT = 0.0;
DECLARE @stDev FLOAT = 1.0;
DECLARE @SEED numeric(18,0) = 1234567890.0; -- seed to ensure list is reproducible
SET NOCOUNT ON;
BEGIN TRAN
UPDATE TestTable
set Randomnumber = @Mean + (2 * SQRT(3) * @stDev) * (( (ID * @SEED ) % 1000 ) / 1000 - 0.5)
COMMIT
-- Check the results
SELECT AVG(RandomNumber) AS mean,
STDEV(RandomNumber ) AS stDev
FROM TestTable;
Run Code Online (Sandbox Code Playgroud)