Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Неявный результат rand()  [new]
Голубев Иван
Member

Откуда: Звенигород
Сообщений: 20
Здравствуйте коллеги, решал задачу генерации номера ОГРН. Задачу решил, другим способом от представленного.

В начале попытался генерить значения от 1 - 9 таким образом.
while ( 1 = 1 )
print nullif(cast(floor(rand() * 10) as integer),0)


В результате получаю вот такие наборы, пустые значения это null:
2
9
9

7
1

2
4

9
3
2
0
7

Знакомый потом предложил, записывать в таблицу и его идея сработала.

Вопрос как раз в том, почему я получаю и null и 0, хотя делаю явное приведение, мало того еще и floor возвращает integer.
25 май 17, 12:05    [20510788]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Голубев Иван
Member

Откуда: Звенигород
Сообщений: 20
Версия: Microsoft SQL Server 2008 R2 (SP2) - 10.50.4290.0 (X64) Aug 5 2013 12:40:54 Copyright (c) Microsoft Corporation Data Center Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

Еще добавлю замечание: в итоге результат оборачивался в isnull(*,1) и таким образом я хотел избавиться от 0.
Проблема в том, что я получаю и 0 и null
25 май 17, 12:12    [20510813]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
AlanDenton
Member [скрыт]

Откуда:
Сообщений: 1004
SELECT TOP(10) *
FROM (
    SELECT t = FLOOR(RAND(CONVERT(VARBINARY, NEWID())) * 10.)
    FROM [master].dbo.spt_values
) t
WHERE t > 0
25 май 17, 12:27    [20510888]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
Голубев Иван,

В функции NULLIF не рекомендуется использовать такие зависимые от времени функции, как RAND(). Это может приводить к тому, что функция будет вычисляться дважды с возвратом различных результатов для каждого из вызовов.

FLOOR(RAND()*9+1)
25 май 17, 12:28    [20510891]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7671
Голубев Иван,

на 2012 тот же эффект. Если использовать переменную, то работает корректно:

while ( 1 = 1 )
begin
	declare @i int = floor(cast(rand()*10.00 as int));
	print nullif(@i, cast(0 as int))
end
25 май 17, 12:33    [20510911]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7671
TaPaK,

точно, в справке указано.
25 май 17, 12:34    [20510920]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
Владислав Колосов,

msdn как-то неоднозначно отвечает?
25 май 17, 12:34    [20510921]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Голубев Иван
Member

Откуда: Звенигород
Сообщений: 20
TaPaK,

Я к сожалению всё равно не могу для себя понять эту фразу. Пускай она 2 раза вычисляется, я же использую явное приведение и ожидаю что в nullif попадёт конкретное целочисленное значение.
25 май 17, 12:39    [20510950]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
Голубев Иван,

Пускай она 2 раза вычисляется. 2 разных значения получается
25 май 17, 12:40    [20510955]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7671
Голубев Иван,

нет, функция выполнит проверку для первого значения RAND(), а результат второго выдаст наружу.
25 май 17, 12:42    [20510967]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Голубев Иван
Member

Откуда: Звенигород
Сообщений: 20
Владислав Колосов,
Спасибо!
25 май 17, 12:49    [20511014]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
Владислав Колосов
Голубев Иван,

нет, функция выполнит проверку для первого значения RAND(), а результат второго выдаст наружу.

ну я склонен думать что отдаёт первый сгенерированный, а для проверки получает второй
25 май 17, 12:52    [20511034]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
Голубев Иван
Member

Откуда: Звенигород
Сообщений: 20
Всем спасибо.
Nullif мы все используем как удобный способ заменить case. А SQL Server просто берет и преобразует его в case
На таком запросе:
select nullif(cast(floor(rand() * 10) as integer),0)
from sys.objects as o


Он преобразует его в:
[Expr1039] = Scalar Operator(CASE WHEN CONVERT(int,floor(rand()*(1.000000000000000e+001)),0)=(0) THEN NULL ELSE CONVERT(int,floor(rand()*(1.000000000000000e+001)),0) END)

На плане это прекрасно видно. Вот и объяснение двум вычислениям.

К сообщению приложен файл. Размер - 33Kb
25 май 17, 13:06    [20511092]     Ответить | Цитировать Сообщить модератору
 Re: Неявный результат rand()  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
Голубев Иван,

всё это сахар и многое другое
25 май 17, 13:09    [20511105]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить