Sql 校验和(NewId())每行执行多次

Sql 校验和(NewId())每行执行多次,sql,sql-server,random,newid,Sql,Sql Server,Random,Newid,在查看代码时,我遇到了一些奇怪的情况,有人读到您可以使用ABS(CHECKSUM(NewId()))%N获得从0到N-1的随机数(因为RAND()不是每行出现),但我怀疑他们并没有真正测试代码(现在简化了表格变量,实际代码做了排名前1的国家/地区,错误地绕过了下面的问题): 执行时会发生以下错误: 子查询返回了多个值。当子查询后跟=、!=、=或子查询用作表达式时,不允许这样做 我的第一个问题是子查询如何返回多个值?为什么有时它根本不返回任何值?(注意不是我现在要问的问题)由以下测试: SELEC

在查看代码时,我遇到了一些奇怪的情况,有人读到您可以使用
ABS(CHECKSUM(NewId()))%N
获得从0到N-1的随机数(因为
RAND()
不是每行出现),但我怀疑他们并没有真正测试代码(现在简化了表格变量,实际代码做了
排名前1的国家/地区
,错误地绕过了下面的问题):

执行时会发生以下错误:

子查询返回了多个值。当子查询后跟=、!=、=或子查询用作表达式时,不允许这样做

我的第一个问题是子查询如何返回多个值?为什么有时它根本不返回任何值?(注意不是我现在要问的问题)由以下测试:

SELECT country FROM @Values v WHERE v.id = ABS(CHECKSUM(NewId())) % 3 + 1
然而,无论执行多少次以下操作:

SELECT ABS(CHECKSUM(NewId())) % 3 + 1
返回的结果总是1,2,3(这是程序员在编写代码时使用的“测试”)

从这一切来看,我怀疑这是因为它正在为每一个比较而不是每一行重新执行,有人能确认这一点并提供一个好的链接来解释这种行为,以便我能向他指出吗?

为什么,这是意料之中的

ABS(校验和(NewId())%3+1
@Values
中的每一行计算一次,因此每一行的值不同

因此,它可以返回多行,或者根本不返回任何行

这正是您在说这个表达式对每一行求值时应该期望的


显然,您实际需要的是一个表达式,该表达式在每个查询中计算一次。

newID将始终在每行调用一次,如果您需要一个唯一的值,请使用以下方法:


ROUND(((3)*RAND()+1),0)

我不明白你在这里说的话。你是说他们选择校验和路由是因为
RAND
不是每行计算的,现在你要问为什么它是每行计算的?@LasseV.Karlsen-看起来他们需要的东西是每外部查询行计算一次,但在传递到子查询时是稳定的。
SELECT*,(从@Values v中选择国家,其中v.id=CA.id)从@Values CROSS-APPLY中选择ABS(CHECKSUM(NewId())%3+1)CA(id)
会这样做,但不保证一定会这样做。@MartinSmith如果你把它作为一个答案,我会接受。
从@Values v中选择国家,其中v.id=CA.id)从@Values CROSS-JOIN中选择ABS(CHECKSUM(NewId())%3+1)CA(id)
也可以工作(可能与交叉应用一样(不)可靠)…即每次执行查询时只计算一次它的值,
交叉应用(选择ABS(CHECKSUM(NewId()))%3+1)CA(id)
如@Martin所指出的,将为父表中的每一行提供唯一值,而不是每次在内部查询中调用
SELECT ABS(CHECKSUM(NewId())) % 3 + 1