sql - CHECKSUM(NewId()) 每行执行多次

标签 sql sql-server random newid

在审查代码时,我遇到了一些奇怪的事情,有人读到您可以使用 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/

相关文章:

java - 如何使用java将三个表连接成一个表以及set方法值应该写在哪里

sql - 选择日期不在多个日期范围 SQL Server 表中的记录

c - 为什么在 c 中使用 rand() 时每个子进程都生成相同的 "random"数字?

C# - DataTable.Merge() 是否添加重复项或更新?

sql - SQL Server 中的自定义日期/时间格式

javascript - 如何使用 JavaScript 获取 -20 到 20 之间的 3 位小数的随机数?

c++ - 使用 std::random_device 在 C++ 中生成随机数

sql - “创建过程”必须是批处理中的唯一语句

php - 解释一个显示销量最高的 3 辆汽车的 MySQLi 查询

sql - 如何通过接受 NULL 值的查询进行 PARTITION BY?