You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单SQL查询中生成并重复NEWID()值?

让NEWID()生成的GUID在关联查询中重复使用的单语句方案

问题场景

需要生成测试数据:先生成N1个唯一的UNIQUEIDENTIFIER值,再通过CROSS APPLY将每个值重复N2次。原SQL写法如下:

SELECT *
FROM (
    SELECT
        S1.value,
        NEWID() AS Id
    FROM GENERATE_SERIES(1, 3) S1
) S1
CROSS APPLY (
    SELECT
        S2.value,
        S1.Id -- 期望重复同一ID值多次
    FROM GENERATE_SERIES(1, 2) S2
) S2
ORDER BY S1.Value, S2.Value

现象与原因

期望每个初始生成的Id被重复多次,但实际每次CROSS APPLY关联时都会生成新的Id。这是因为NEWID()属于非确定性函数,SQL优化器的设计会导致这类函数的执行时机不固定——即使放在子查询中,优化器可能会选择在关联阶段重新执行它,而非保留子查询中生成的结果。

单语句解决方案

以下几种单语句写法可以实现需求,核心是确保NEWID()仅在生成基础行时执行一次,后续关联复用该值:

方案1:将NEWID()绑定到基础行的独立APPLY中

SELECT
    S1.value AS BaseValue,
    S2.value AS RepeatValue,
    GuidGen.Id
FROM GENERATE_SERIES(1, 3) S1
CROSS APPLY (SELECT NEWID() AS Id) AS GuidGen -- 每个基础行仅生成一次GUID
CROSS APPLY GENERATE_SERIES(1, 2) S2
ORDER BY S1.value, S2.value;

方案2:用OFFSET强制物化子查询

通过OFFSET 0 ROWS提示优化器物化子查询,固定NEWID()的结果:

SELECT *
FROM (
    SELECT
        S1.value,
        NEWID() AS Id
    FROM GENERATE_SERIES(1, 3) S1
    OFFSET 0 ROWS -- 强制子查询执行并保留结果
) S1
CROSS APPLY (
    SELECT
        S2.value,
        S1.Id
    FROM GENERATE_SERIES(1, 2) S2
) S2
ORDER BY S1.Value, S2.Value;

方案3:使用CTE结合物化提示(部分SQL方言支持)

如果CTE默认不被物化,可添加提示强制:

WITH BaseIds AS (
    SELECT
        S1.value,
        NEWID() AS Id
    FROM GENERATE_SERIES(1, 3) S1
    OPTION (MAXDOP 1) -- 部分环境下可强制物化,视数据库方言调整
)
SELECT
    B.value AS BaseValue,
    S2.value AS RepeatValue,
    B.Id
FROM BaseIds B
CROSS APPLY GENERATE_SERIES(1, 2) S2
ORDER BY B.value, S2.value;

总结

非确定性函数的执行时机由优化器决定,通过调整写法将函数的执行绑定到基础行生成阶段,即可实现GUID的重复复用。如果上述单语句方案在你的数据库环境中不生效,临时表仍是最稳妥的替代方案。

内容的提问来源于stack exchange,提问作者T N

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:52:38