如何获得 CTE 中生成的随机数,使其在 JOIN 中不发生更改?

eli*_*abk 6 sql sql-server random common-table-expression

问题

我使用这种技术#Table_1为 CTE中表中的每一行生成一个随机数。然后我将 CTE 的结果加入到另一个表 上。我不是为 中的每一行获取随机数,而是为连接中的每个结果行获取一个新的随机数!#Table_2#Table_1

CREATE TABLE #Table_1 (Id INT)

CREATE TABLE #Table_2 (MyId INT, ParentId INT)

INSERT INTO #Table_1
VALUES (1), (2), (3)

INSERT INTO #Table_2
VALUES (1, 1), (2, 1), (3, 1), (4, 1), (1, 2), (2, 2), (3, 2), (1, 3)


;WITH RandomCTE AS
(
    SELECT Id, (ABS(CHECKSUM(NewId())) % 5)RandomNumber
    FROM #Table_1
)
SELECT r.Id, t.MyId, r.RandomNumber
FROM RandomCTE r
INNER JOIN #Table_2 t
    ON r.Id = t.ParentId
Run Code Online (Sandbox Code Playgroud)

结果

Id          MyId        RandomNumber
----------- ----------- ------------
1           1           1
1           2           2
1           3           0
1           4           3
2           1           4
2           2           0
2           3           0
3           1           3
Run Code Online (Sandbox Code Playgroud)

期望的结果

Id          MyId        RandomNumber
----------- ----------- ------------
1           1           1
1           2           1
1           3           1
1           4           1
2           1           4
2           2           4
2           3           4
3           1           3
Run Code Online (Sandbox Code Playgroud)

我尝试过的

我试图通过将随机数转换为 来模糊优化器生成随机数的逻辑VARCHAR,但这不起作用。

我不想做什么

我想避免使用临时表来存储 CTE 的结果。

如何在不使用临时存储的情况下为表生成随机数并在联接中保留该随机数?

use*_*983 2

这似乎可以解决问题:

WITH CTE AS(
    SELECT Id, (ABS(CHECKSUM(NewId())) % 5)RandomNumber
    FROM #Table_1),
RandomCTE AS(
    SELECT Id,
           RandomNumber
    FROM CTE
    GROUP BY ID, RandomNumber)
SELECT *
FROM RandomCTE r
INNER JOIN #Table_2 t
    ON r.Id = t.ParentId;
Run Code Online (Sandbox Code Playgroud)

看起来 SQL Server 意识到,在 CTE 之外,实际上RandomNumber只是NEWID()在其周围包含了一些附加函数(DB<>Fiddle),因此它仍然为每行生成一个唯一的 ID。因此,第二个 CTE 中的子句GROUP BY强制数据引擎定义 RandomNumber 一个值,以便它可以执行GROUP BY.