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

CASE表达式返回异常NULL值:SQL加权随机编码问题求助

问题原因与解决方案

异常原因

你在第二个查询的CASE表达式中,直接将调用crypt_gen_random(1)的逻辑嵌入到了CASE的判断条件里。由于crypt_gen_random是非确定性函数(每次调用都会生成新的随机值),SQL Server的查询优化器可能会在执行过程中多次调用该函数,导致CASE判断时使用的随机值和实际截取字符的随机值不一致。比如,某次执行时,截取字符得到的是'1',但CASE比较时又生成了新的随机值,导致没有匹配到任何WHEN分支,最终返回NULL。

简单来说:同一个行里,CASE表达式里的随机函数被执行了多次,导致截取的字符和判断的字符不是同一个,从而出现无匹配的情况,返回NULL。

解决办法

先将随机生成的字符提取到一个临时子查询或CTE的列中,确保每行只调用一次随机函数,再对这个固定的字符进行CASE映射。这样就能保证CASE判断使用的是同一个随机生成的字符,不会出现无匹配的NULL。

修改后的代码如下:

--
--  Expecting 1 = 50% , 2 = 35%, 3 = 15%
--
declare @weightedKeys varchar(100)
select @weightedKeys =
    '11111111111111111111111111111111111111111111111111' + -- 50
    '22222222222222222222222222222222222' + -- 35
    '333333333333333' -- 15
;with a(k) as
(
    select 1 as k
    union all
    select k + 1 from a where k < 99+1
),
t2 as
(
    select row_number() over(order by x.k) as k
    from a x, a y, a z 
), 
chance as
(
    -- 先在子查询中生成固定的随机字符,再进行CASE映射
    select
        case temp.key_char
            when '1' then '1-One' 
            when '2' then '2-Two'
            when '3' then '3-Three'
        end as test_group
    from (
        select
            substring(@weightedKeys, ((convert(tinyint,crypt_gen_random(1))*100)/256)+1, 1) as key_char
        from t2
    ) as temp
)
--check the results
select test_group, count(1) as total
from chance
group by test_group
order by count(1) desc

验证效果

修改后,每个行只会调用一次crypt_gen_random生成随机位置,截取到的字符必然是'1'/'2'/'3'中的一个,CASE映射时能准确匹配到对应的分支,不会再出现NULL值,同时保持1:50%、2:35%、3:15%的权重比例。

内容的提问来源于stack exchange,提问作者Ian Wells

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 07:43:11