Головоломка TSQL, почему мое обновление не случайное?

Я смотрел вопрос 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 напрямую, все распределяется правильно?

Может ли кто-нибудь подтвердить, что это работает так же в 2008 году, мой тест был на 2005 sp1.

Sam Saffron 16.01.2009 07:46
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
694
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

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

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

твои мысли?

edit: также я тестировал в sql server express 2008, и это тот же результат.

Я думаю, вы знаете что-то, что имеет смысл и коррелирует с результатами.

Sam Saffron 16.01.2009 08:05

это беспокоило меня около 20 минут, пришлось открыть ssms и все остальное, чтобы посмотреть, смогу ли я найти хороший ответ.

John Boker 16.01.2009 08:06

@ Джон Бокер: интересное наблюдение. Кажется ошибкой, если выражения вычисляются на лету для каждого КОГДА

Michael Buen 16.01.2009 08:35

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

Также обратите внимание, что функция 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

Другие вопросы по теме