带RAND的SQL多次插入-如何更改RAND值

时间:2018-10-20 08:18:46

标签: sql sql-server sql-insert

我有一条语句,它根据一个随机值和另一个值将值插入表中

INSERT INTO TRAINER_SYNC (Steps, TrainerId, SyncDate)
SELECT AverageSteps * (RAND()*(1.15-0.85)+0.85), Id, GETDATE()
FROM TRAINER

这很好,但是只要两个“ Trainers”具有相同的“ AverageSteps”,插入表中的数字就始终相同。

例如,如果所有培训师的平均步数为10000,则这是TRAINER_SYNC表中的结果

Id  TrainerId   SyncDate                    Steps
10  1           2018-10-20 18:42:16.407     9482
11  2           2018-10-20 18:42:16.407     9482
12  3           2018-10-20 18:42:16.407     9482
13  4           2018-10-20 18:42:16.407     9482
14  5           2018-10-20 18:42:16.407     9482
15  6           2018-10-20 18:42:16.407     9482
16  7           2018-10-20 18:42:16.407     9482
17  8           2018-10-20 18:42:16.407     9482
18  9           2018-10-20 18:42:16.407     9482

有没有一种方法可以使插入语句中的RAND()更加“随机”?我不知道它叫什么,但是重置初始种子,以便插入的每次迭代都给我一个不同的随机值?

2 个答案:

答案 0 :(得分:0)

您可以使用

1)  RAND(CHECKSUM(NEWID()))

OR

2)

INSERT INTO TRAINER_SYNC (Steps, TrainerId, SyncDate)
    SELECT AverageSteps * (RAND(AverageSteps)*(1.15-0.85)+0.85), Id, GETDATE()
    FROM TRAINER

答案 1 :(得分:0)

rand()是一类特殊的函数,对于SQL语句中的每个调用,该函数仅被评估一次。这可能确实令人困惑,因为:

select rand(), rand()

返回两个不同的值。但是,

select rand(), rand()
from (values (1), (2), (3)) v(x)

返回三行-每行具有相同的两个值。这是SQL Server的优化“功能”。我相信getdate()(和类似的日期/时间函数)是唯一具有此行为的其他函数。

通常的解决方案是将newid()植入随机数生成器。但是,返回类型不同,因此checksum()用于将id转换为数字:

INSERT INTO TRAINER_SYNC (Steps, TrainerId, SyncDate)
    SELECT AverageSteps * (RAND(CHECKSUM(NEWID()))*(1.15-0.85)+0.85), 
           Id, GETDATE()
    FROM TRAINER;

您可以使用其他种子(如果有)。例如,如果每个培训师只参加一行,则可以使用rand(id)。我应该注意,rand()并不是特别具有种子“随机性”,因此相邻种子通常会产生相似的数字。

您可能不应该在GETDATE()中设置INSERT。您可以使用以下方法创建表:

SyncDate datetime default getdate()

因此默认值为插入时间。