TSQL головоломка, почему мое обновление не случайно? - PullRequest
4 голосов
/ 16 января 2009

Я смотрел на вопрос 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

Данные для обоих наборов результатов были сгенерированы в одном и том же операторе обновления.

Итак, мой вопрос: почему число из диапазона от 0 до 5 попадает в мой регистр? Что это за номер? Почему, когда я обновляю int напрямую, вещи распределяются правильно?

Ответы [ 3 ]

5 голосов
/ 16 января 2009

У меня есть идея:

возможно, значение вычисляется для каждого оператора when, если оно попадает к первому, вычисляет значение, отличное от 0, переходит ко второму, затем вычисляется значение, отличное от 1, затем к следующему и т. Д., если он доходит до 5, а затем вычисляет число, отличное от 5, он переходит к другому.

это также объясняет, почему существует так много «КАК ЭТО ВОЗМОЖНО», чем другие, остальные увеличиваются, когда текущая позиция и случайное число, сгенерированное в этой позиции, совпадают.

ваши мысли?

edit: также я тестировал SQL Server Express 2008, и это тот же результат.

1 голос
/ 16 января 2009
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
0 голосов
/ 16 января 2009

Джон, вероятно, прав ... хотя он беспокоится, что "КОГДА" будет настолько неэффективным.

Также обратите внимание, что функция NewId () возвращает новое значение каждый раз, когда вы вызываете его. Вы называете это дважды (не считая странности "когда"). Следующее является более стабильным: Drop Table # Buildings идти

создать таблицу #Buildings ([Use] varchar (50), n int)

insert #Buildings выберите ноль, нуль из системных объектов

объявить @nid как уникальный идентификатор

обновление # Здания set @nid = newid (), [Использовать] = case (ABS (CAST (CAST (NewId () AS VARBINARY) AS int))% 6) когда 0, то ноль когда 1, то «склад» когда 2, то «офис» когда 3, то «рынок» когда 4, то «в розницу» когда 5, то «мастерская» еще «КАК ЭТО ВОЗМОЖНО» конец, n = ABS (CAST (CAST (NewId () как VARBINARY), как int))% 6

выберите [Использовать], количество (*) из

Здания

сгруппировать по [Использовать]

выберите n, count (*) из

Здания

группировка по n

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...