Sql 迭代cte中的随机值

Sql 迭代cte中的随机值,sql,sql-server,random,common-table-expression,Sql,Sql Server,Random,Common Table Expression,使用SQL Server 2016+ 我在从一个表中选择随机行时遇到了一些困难,这个表被缩小为一个如何生成随机数的问题。为了提高效率,使用NEWID的前10个*订单会降低速度。在下面的代码中,我使用了一个可重复结果的种子集,但在live中我不会这样做 代码示例: SELECT RAND(100) RN , RAND() , RAND() , RAND() , RAND(); SELECT RAND(100) RN UNION ALL SELE

使用SQL Server 2016+

我在从一个表中选择随机行时遇到了一些困难,这个表被缩小为一个如何生成随机数的问题。为了提高效率,使用NEWID的前10个*订单会降低速度。在下面的代码中,我使用了一个可重复结果的种子集,但在live中我不会这样做

代码示例:

SELECT  RAND(100) RN
,       RAND()
,       RAND()
,       RAND()
,       RAND();

SELECT  RAND(100) RN
UNION ALL SELECT  RAND()
UNION ALL SELECT  RAND()
UNION ALL SELECT  RAND()
UNION ALL SELECT  RAND();

WITH cte AS
    (SELECT 1         ID
     ,      RAND(100) RN
     UNION ALL
     SELECT cte.ID + 1
     ,      RAND()
       FROM cte
      WHERE ID < 5)
SELECT  RN
  FROM  cte;
正如您可以从结果中看到的,当我在线或通过联合重复调用RAND函数时,每次调用都会得到不同的结果。然而,如果我在迭代cte中调用函数,那么我会重复得到相同的值

此代码是显示问题的示例,而不是整个代码集。我创建此示例纯粹是为了演示这个问题。我有一个基于Checksum&NewID和模调用以及乘法的组合的解决方案,可以给我想要的范围内的值,但是这相当复杂,而且对于仅仅生成一个范围内的随机数列表来说似乎太过分了

我正在寻找任何可以提供的指导

为什么会这样 有什么办法解决这个问题吗 用于生成非RBAR的随机数列表的其他选项 非常感谢。

兰德在查询中返回一个常量值。也就是说,在查询中,每次提及都会对其进行一次评估

如果运行以下命令,您可以看到:

select rand(), rand()
from (values (1), (2), (3)) v(x);
每行有两个不同的值。但是,这些列具有相同的值

在任何情况下,标准答案都是使用RANDCHECKSUMNEWID。这在每次调用时为RAND提供一个随机种子:

WITH cte AS
    (SELECT 1 as ID, RAND(CHECKSUM(NEWID())) as RN
     UNION ALL
     SELECT cte.ID + 1, RAND(CHECKSUM(NEWID())) as RN
     FROM cte
     WHERE ID < 5
    )
SELECT RN
FROM cte;

这可能足以获得一个随机值列表。我怀疑您真正的问题是不同的——类似于从表中提取随机行。如果这是真正的问题,请提出一个新问题或检查类似问题。

-根据SQL Server上的其他一些建议,有时每个SQL语句只计算一次函数-例如,您将看到GetDate的相同效果,它不会在任何查询上递增,无论选择记录花费多长时间-如您所说,NewId没有展示这一点,所以它可以满足你的需要。我相信,这背后的部分原因是绩效,谢谢大家。我已经看到了这些类型的解决方案。ORDERBY NewID在大型表上变得非常低效,我现有的解决方法是基于映射到一行的NewID的绝对校验和。这些都是很好的帖子,我相信如果他们登陆这里,他们会帮助其他人。>>生成非RBAR随机数列表的其他选项-从某处下载数百万位数的pi,并将其放入带有id的表格中,然后你需要做的就是生成一个随机id作为种子,然后你可以取下面的pi数字-newid本身是不是效率低下,或者只是排序的代价?回答不错,我很欣赏这些例子
WITH cte AS
    (SELECT 1 as ID, RAND(CHECKSUM(NEWID())) as RN
     UNION ALL
     SELECT cte.ID + 1, RAND(CHECKSUM(NEWID())) as RN
     FROM cte
     WHERE ID < 5
    )
SELECT RN
FROM cte;