Я смотрел вопрос 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 попадает в мой оператор case? Что это за номер? Почему, когда я обновляю int напрямую, все распределяется правильно?





У меня есть идея:
возможно, значение вычисляется для каждого оператора when, если оно доходит до первого, вычисляет значение, отличное от 0, оно переходит ко второму, затем вычисляет значение, отличное от 1, затем следующее и так далее, если оно делает это путь к 5, а затем вычисляет число, отличное от 5, которое переходит к else.
это также объяснило бы, почему существует намного больше «КАК ЭТО ВОЗМОЖНО», чем других, остальные увеличиваются, когда текущая позиция и случайное число, сгенерированное в этой позиции, совпадают.
твои мысли?
edit: также я тестировал в sql server express 2008, и это тот же результат.
Я думаю, вы знаете что-то, что имеет смысл и коррелирует с результатами.
это беспокоило меня около 20 минут, пришлось открыть ssms и все остальное, чтобы посмотреть, смогу ли я найти хороший ответ.
@ Джон Бокер: интересное наблюдение. Кажется ошибкой, если выражения вычисляются на лету для каждого КОГДА
Джон, вероятно, прав ... хотя он беспокоит, что "КОГДА" будет настолько неэффективным.
Также обратите внимание, что функция NewId () возвращает новое значение каждый раз, когда вы ее вызываете. Вы называете это дважды (не считая странности "когда"). Следующее более стабильно: drop table #Buildings идти
создать таблицу #Buildings ([Использовать] varchar (50), n int)
вставить # Здания выберите null, null из sysobjects
объявить @nid как uniqueidentifier
update #Buildings установить @nid = newid (), [Использовать] = case (ABS (CAST (CAST (NewId () AS VARBINARY) AS int))% 6) когда 0, то ноль когда 1 то склад когда 2 тогда "офис" когда 3 тогда "рынок" когда 4 тогда "розничная" когда 5 тогда "мастерская" else "КАК ЭТО ВОЗМОЖНО" конец, n = ABS (CAST (CAST (NewId () AS VARBINARY) AS int))% 6
выберите [Использовать], отсчитайте (*) от
сгруппировать по [Использовать]
выберите n, посчитайте (*) от
группа по n
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
Может ли кто-нибудь подтвердить, что это работает так же в 2008 году, мой тест был на 2005 sp1.