Sql server rand(checksum(newid())的T-SQL sum()如果在选择列表中多次出现,是否不是随机的?

Sql server rand(checksum(newid())的T-SQL sum()如果在选择列表中多次出现,是否不是随机的?,sql-server,tsql,random,aggregate-functions,Sql Server,Tsql,Random,Aggregate Functions,表达式randchecksumnewid通常用于生成随机数 在生成一些测试数据时,我执行了以下语句: select rand(checksum(newid())) R1, rand(checksum(newid())) R2 from ftSequence(3) 其中,ftSequenceN是一个表函数,返回单列N,其行中的值为1、2、3…N,与参数N的值相同。运行该函数会产生非常预期的数据: R1 R2 ---------------------- -

表达式randchecksumnewid通常用于生成随机数

在生成一些测试数据时,我执行了以下语句:

select rand(checksum(newid())) R1, rand(checksum(newid())) R2
from ftSequence(3)
其中,ftSequenceN是一个表函数,返回单列N,其行中的值为1、2、3…N,与参数N的值相同。运行该函数会产生非常预期的数据:

R1                     R2
---------------------- ----------------------
0,817                  0,9515
0,3043                 0,3947
0,5336                 0,7963
然后有必要在每一列中找到总和,我做到了:

select sum(rand(checksum(newid()))) S1, sum(rand(checksum(newid()))) S2
from ftSequence(3)
令人惊讶的是,我在每一列中都得到了相同的数字:

S1                     S2
---------------------- ----------------------
1,2276                 1,2276
为什么会这样? avg、min和max聚合函数的行为相同。 是查询优化器,还是我遗漏了一些逻辑

在评论之后进行更多的观察

将sumrandchecksumnewid放入CTE或类似子查询

select
    (select sum(rand(checksum(newid()))) from ftSequence(3)) S1,
    (select sum(rand(checksum(newid()))) from ftSequence(3)) S2

以及做一个像这样的把戏

select
    sum(rand(checksum(newid()))) S1
    , sum(rand(checksum(newid())) + 0) S2
from ftSequence(3)
工作,产生不同的价值观

S1                     S2                    
---------------------- ----------------------
0,7349                 1,478                 
对此我很高兴,并且需要从ftSequence3生成多行不同的avgrandchecksumnewid,我做了以下工作

select R.*
from ftSequence(3) S1
    cross join (
        select
            avg(rand(checksum(newid()))) R1,
            avg(rand(checksum(newid())) + 0) R2
        from ftSequence(3)
    ) R
并得到如下结果:

R1                     R2
---------------------- ----------------------
0,6464                 0,4501
0,6464                 0,4501
0,6464                 0,4501

在这一点上,我无法回答自己,这是正确的结果,还是所有的值都是随机的?有什么方法可以使所有的值都是随机的?

正如我在问题中所说的,我需要一组随机测试数据,但不是均匀分布的随机数,我需要一组随机数

select avg(rand(checksum(newid()))) from ftSequence(@n)
收敛到高斯分布

我发现,我可以使用cross-apply语句代替交叉连接,并对外部范围数据进行额外的无意义检查:

declare @rCnt int, @n int
set @rCnt = 5000000
set @n = 5

select R.*
from ftSequence(@rCnt) S
    cross apply (
        select
            avg(rand(checksum(newid())) + 1e-101) R1,
            avg(rand(checksum(newid())) + 1e-102) R2,
            avg(rand(checksum(newid())) + 1e-103) R3
        from ftSequence(@n)
        where S.N is not NULL
    ) R
然而,我不确定这是否是一种可靠的方法

以下可能是更可靠的替代方案:

declare @rCnt int, @n int
set @rCnt = 5000000
set @n = 5

create table #Rand (ValNo int, R1 float, R2 float, R3 float)
create clustered index #IX_Rand on #Rand (ValNo)

insert into #Rand
select
    S.N / @n,
    rand(checksum(newid())) R1,
    rand(checksum(newid())) R2,
    rand(checksum(newid())) R3
from ftSequence(@n * @rCnt) S

select AVG(R.R1), AVG(R.R2), AVG(R.R3)
from #Rand R
group by ValNo

有趣的是,这里还有一个不依赖于序列函数的测试:-预期结果,不同的和从选择randchecksumnewid R1中选择SUMR1'R1 Sum',从选择randchecksumnewid R2中选择SUMR2'R2 Sum',从sys.objects中选择名称v-意外结果,相同的和从sys.objects中选择SumrCheckSumnewid S1,从SymrandCheckSumnewid S2有趣的问题:答案很简单,在本例中,它会计算一次。我不确定是否有可靠的方法来抑制它并重新计算它。我不确定randchecksumnewid是否收敛到高斯分布,是吗?您可以使用SELECT SQRT-2*LogAbsCastCrypt_GEN_RANDOM8作为BIGINT作为FLOAT/9223372036854775807*COS2*PI*ABSCASTCASTCRYPT_GEN_RANDOM8与FLOAT一样重要/9223372036854775807Afaik,randchecksumnewid是一致的,但根据中心极限定理,它们序列的平均值收敛到高斯。当然,平均值越小,近似值越差,但在我的情况下,这是可以接受的。
declare @rCnt int, @n int
set @rCnt = 5000000
set @n = 5

create table #Rand (ValNo int, R1 float, R2 float, R3 float)
create clustered index #IX_Rand on #Rand (ValNo)

insert into #Rand
select
    S.N / @n,
    rand(checksum(newid())) R1,
    rand(checksum(newid())) R2,
    rand(checksum(newid())) R3
from ftSequence(@n * @rCnt) S

select AVG(R.R1), AVG(R.R2), AVG(R.R3)
from #Rand R
group by ValNo