【发布时间】:2019-11-10 06:39:04
【问题描述】:
使用 SQL Server 2016+
我在从表中选择随机行时遇到了一些困难,该表已缩小为随机数生成方式的问题。为了提高效率,使用TOP 10 * ORDER BY NEWID() 会变慢。在下面的代码中,我使用了一组种子来获得可重复的结果,但在现场我不会。
代码示例:
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;
结果集
RN
---------------------- ---------------------- ---------------------- ---------------------- ----------------------
0.715436657367485 0.28463380767982 0.0131039082850364 0.28769876521071 0.100505471175005
(1 row affected)
RN
----------------------
0.715436657367485
0.28463380767982
0.0131039082850364
0.28769876521071
0.100505471175005
(5 rows affected)
RN
----------------------
0.715436657367485
0.28463380767982
0.28463380767982
0.28463380767982
0.28463380767982
(5 rows affected)
从结果中可以看出,当我调用 RAND() 函数重复内联或通过联合时,每次调用都会得到不同的结果。但是,如果我在迭代 cte 中调用该函数,那么我会重复相同的值。
此代码是显示问题的示例,而不是整个代码集。我创建这个纯粹是为了演示这个问题。我有一个基于Checksum 和NewID() 组合的解决方案,以及模数调用和乘法来给我想要的范围内的值,但这相当复杂,而且对于仅在范围。
我正在寻找任何可以提供的指导
- 为什么会这样
- 解决问题的任何方法
- 生成随机数列表的其他选项(非 RBAR)
非常感谢。
【问题讨论】:
-
关于stackoverflow.com/questions/848872/…的一些其他建议
-
SQL Server 有时只对每个 SQL 语句计算一次函数 - 例如,您会看到使用 GetDate() 的相同效果,无论选择记录花费多长时间,它都不会在任何查询上增加 - 正如您所说, NewId() 没有表现出这一点,所以它适用于你想要的。我相信,其背后的原因部分是性能
-
谢谢大家。我已经看到了这类解决方案。按 NewID() 排序在大型表上变得非常低效,我现有的解决方法是基于映射到一行的 newid 的绝对校验和。这些都是好帖子,我相信如果他们登陆这里,他们会帮助其他人。
-
>>生成随机数列表的其他选项(不是 RBAR) - 从某个地方下载数百万位数的 pi 并将其放入带有 id 的表中,然后您需要做的就是是生成一个随机 id 作为种子,那么您可以获取以下 pi 数字 - newid() 本身效率低下,还是只是排序的成本?
标签: sql sql-server random common-table-expression