在审查代码时,我遇到了一些奇怪的事情,有人读到您可以使用 ABS(CHECKSUM(NewId())) % N
来获取从 0 到 N-1 的随机数(如RAND()
不会每行发生),但我怀疑他们并没有真正测试他们的代码(现在使用表变量进行简化,实际代码做了 TOP 1 国家
错误地解决了下面的问题):
DECLARE @Values TABLE
(
id int identity,
country VARCHAR(100)
)
INSERT INTO @Values (country) VALUES ('UK'), ('USA'), ('China')
SELECT *, (SELECT country FROM @Values v WHERE v.id = ABS(CHECKSUM(NewId())) % 3 + 1)
FROM @Values
执行时出现以下错误:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
我的第一个问题是子查询如何返回多个值?为什么有时它根本不返回任何值? (注意不是我在SO问的问题)测试者:
SELECT country FROM @Values v WHERE v.id = ABS(CHECKSUM(NewId())) % 3 + 1
但是无论执行以下次数多少次:
SELECT ABS(CHECKSUM(NewId())) % 3 + 1
返回的结果始终是1,2,3(这是程序员在编写代码时使用的“测试”)
从这一切来看,我怀疑这是因为它是为每次比较而不是每一行重新执行的,有人可以确认这一点并提供一个很好的链接来解释这种行为,以便我可以向他指出吗?
最佳答案
为什么,这是预料之中的。
ABS(CHECKSUM(NewId())) % 3 + 1
针对 @Values
中的每一行计算一次,因此每一行都有不同的值。
因此它可以返回多行,或者根本不返回任何行。
这正是您在说“此表达式对每一行进行计算”时所期望的结果。
显然,您真正想要的是每个查询计算一次的表达式。
关于sql - CHECKSUM(NewId()) 每行执行多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9463938/