遵循(简化)代码片段的目的是返回 一个随机行 。不幸的是,当我们在查询分析器中运行此片段时,它返回的结果介于零到三个之间。
由于我们的输入表正好由5个具有唯一ID的行组成,并且当我们在此表上执行ID 等于 随机数的选择时,我们感到困惑的是,返回的行将不止一个。
注意:除其他外,我们已经尝试过将校验和结果转换为无用的整数。
DECLARE @Table TABLE ( ID INTEGER IDENTITY (1, 1) , FK1 INTEGER ) INSERT INTO @Table SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 SELECT * FROM @Table WHERE ID = ABS(CHECKSUM(NEWID())) % 5 + 1
我们的使用场景如下所示(请不要评论是否做正确的事。这是决定的力量)
最终,我们必须创建一个具有 实际 值的结果,通过从表本身中随机选择现有的权重来 混淆 生产者和权重的组合。 然后查询将变成这样(也是RAND无法使用的原因)
RAND
SELECT t.ID , FK1 = (SELECT FK1 FROM @Table WHERE ID=ABS(CHECKSUM(NEWID())) % 5 + 1) FROM @Table t
因为内部选择可能返回零结果,所以它将再次返回NULL值,这是不可接受的。究其原因,是内部选择为什么在零和x结果之间返回的调查(这甚至是英语吗?)。
对我来说,亮起的ABS(CHECKSUM(NEWID())) % 5 + 1)是对 每一行 进行了重新评估的简单观察。我的印象是,ABS(CHECKSUM(NEWID())) % 5 + 1)应该先评估 一次 ,然后再进行匹配。
ABS(CHECKSUM(NEWID())) % 5 + 1)
谢谢大家的回答,虽然缓慢但确实可以使我更好地理解。
发生这种情况的原因是因为NEWID()为表中的每一行提供了不同的值。对于每一行, 独立于其他行 ,有五分之一的机会将其返回。因此,就目前而言,实际上所有5行返回的概率为3125分之一!
要查看此信息,请运行以下查询。您会看到每一行都有一个不同的ID。
SELECT * , NEWID() FROM @Table
这将修复您的代码:
DECLARE @Id int SET @Id = ABS(CHECKSUM(NEWID())) % 5 + 1 SELECT * FROM @Table WHERE ID = @Id
但是,我不确定这是从表中选择单个随机行的最有效方法。
您可能会发现此MSDN文章很有用:http : //msdn.microsoft.com/zh-cn/library/Aa175776(T-SQL中的随机抽样)
编辑1 :现在我考虑一下, 假设行数保持固定并且ID保证是连续的 ,这可能是最有效的方法。
编辑2 :当用作子查询时,要获得所需的结果,请使用TOP 1,如下所示:
SELECT t.ID , FK1 = (SELECT TOP 1 FK1 FROM @Table ORDER BY NEWID()) FROM @Table t