代码之家  ›  专栏  ›  技术社区  ›  Sam Saffron James Allen

TSQL拼图,为什么我的更新不是随机的?

  •  4
  • Sam Saffron James Allen  · 技术社区  · 16 年前

    我在看Postgres问题,它要求用随机值更新一个表。

    我只注意到它在回答后是针对Postgres的,但在回答它时,我发现了一个谜。

    以下是我的示例代码:

    create table #Buildings([Use] varchar(50), n int)
    
    insert #Buildings
    select null,null from sysobjects 
    
    update #Buildings
    set [Use] = 
            case (ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 6)
                when 0 then null
                when 1 then 'warehouse'
                when 2 then 'office'
                when 3 then 'market'
                when 4 then 'retail'
                when 5 then 'workshop'
                else 'HOW IS THIS POSSIBLE'
            end,
        n = ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 6
    
    select [Use], count(*) from
    #Buildings
    group by [Use] 
    
    select n, count(*) from
    #Buildings
    group by n 
    

    它返回一个非常奇怪的结果集:

    Use                                                
    -------------------------------------------------- -----------
    workshop                                           128
    HOW IS THIS POSSIBLE                               633
    NULL                                               287
    retail                                             140
    warehouse                                          258
    market                                             177
    office                                             209
    

    以及第二个完全有意义的结果集:

    n           
    ----------- -----------
    0           292
    3           300
    1           313
    4           277
    5           311
    2           339
    

    两个结果集的数据是在同一个update语句中生成的。

    所以我的问题是为什么一个数字超出了0-5的范围,击中了我的案例陈述?那是什么号码?为什么当我直接更新int时,所有的东西都是正确分布的?

    3 回复  |  直到 16 年前
        1
  •  5
  •   John Boker    16 年前

    我有个主意:

    可能每个when语句都在计算这个值,如果它到达第一个语句,计算一个不是0的值,它转到第二个语句,然后计算一个不是1的值,然后计算下一个等等,如果它到达5,然后计算一个不是5的数,它转到其他语句。

    这也解释了为什么有如此多的“这是怎么可能的”比其他人,其他人是增量时,当前的位置和随机数产生的位置匹配。

    你的想法?

    编辑:我也在SQL Server Express 2008中测试过,结果是一样的。

        2
  •  1
  •   Michael Buen    16 年前
    create table #Buildings([Use] varchar(50), n int)    
    insert #Buildings
    select null,null from sysobjects 
    
    
    
    
    declare @i int
    
    update #Buildings
    set 
        @i = (ABS(CAST(CAST(NEWID() AS VARBINARY) AS int)) % 6),
        [Use] = 
            case @i -- if the expression is evaluated on-the-fly for each WHEN, MSSQL variable-in-SQL capability will alleviate this problem
                    when 0 then null
                    when 1 then 'warehouse'
                    when 2 then 'office'
                    when 3 then 'market'
                    when 4 then 'retail'
                    when 5 then 'workshop'
                    else 'HOW IS THIS POSSIBLE'
            end,
        n = @i
    
    select [Use], count(*) from
    #Buildings
    group by [Use] 
    
    select n, count(*) from
    #Buildings
    group by n
    
        3
  •  0
  •   user53794    16 年前

    约翰可能是对的…尽管它担心“何时”效率会如此低下。

    还要注意,newid()函数每次调用它时都会返回一个新值。你叫它两次(不算什么时候的“Wierdness”)。以下更为稳定: 升降台建筑 去

    创建表建筑物([使用]varchar(50),n int)

    插入建筑物 从sysobjects中选择空值和空值

    将@nid声明为uniqueidentifier

    更新建筑物 设置@nid=newid(), [使用] case(abs(cast(cast(newid()as varbinary)as int))%6) 当0时,则为空 当1然后“仓库” 当2时,然后是“办公室” 当3时,然后是“市场” 当4点,然后“零售” 5点,然后是“车间” 否则“这怎么可能” 结束, n=abs(cast(cast(newid()as varbinary)as int))%6

    选择[使用],计数(*)从

    建筑

    按[使用]分组

    选择n,count(*)from

    建筑

    N组