Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как получить одинаковый GUID / 25 сообщений из 27, страница 1 из 2
15.01.2018, 15:44
    #39584525
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Доброго дня, коллеги!

Возможно что-то где-то не дочитал, вопрос к тем кто дочитал. Почему вот этот запрос:

Код: sql
1.
2.
3.
4.
SELECT x.n, a.id
  FROM (SELECT NEWID() n) x
  JOIN (SELECT 1 id UNION ALL SELECT 2) a
    ON 1=1



Возвращает разные гуиды хотя по логике запрос в секции FROM должен выполняться 1 раз и должен вернуть 1 значение. Это происки оптимизатора? Никак нельзя получить одинаковый гуид без использования переменной?
...
Рейтинг: 0 / 0
15.01.2018, 15:51
    #39584528
Maxx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
а план посмотреть слабо ? там все написанно.. ведь
...
Рейтинг: 0 / 0
15.01.2018, 15:56
    #39584533
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Drunik,

Код: sql
1.
SELECT TOP (SELECT 1) NEWID()


но это вроде баг
...
Рейтинг: 0 / 0
15.01.2018, 15:57
    #39584535
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Maxxа план посмотреть слабо ? там все написанно.. ведь

написанно обычно в подъезде... вот план

|--Compute Scalar(DEFINE:([Expr1000]=newid()))
|--Constant Scan(VALUES1)),((2))))

Мне от этого плана легче не стало. Я понимаю что обращение происходит к функции 2 раза - я не понимаю почему? И можно ли что то сделать чтобы это обращение делалось 1 раз?
...
Рейтинг: 0 / 0
15.01.2018, 15:59
    #39584537
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
TaPaKDrunik,

Код: sql
1.
SELECT TOP (SELECT 1) NEWID()


но это вроде баг

Спасибо, но это тоже не помогает.
...
Рейтинг: 0 / 0
15.01.2018, 16:01
    #39584539
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
DrunikTaPaKDrunik,

Код: sql
1.
SELECT TOP (SELECT 1) NEWID()


но это вроде баг

Спасибо, но это тоже не помогает.

Код: sql
1.
2.
3.
4.
SELECT 
	(SELECT TOP (SELECT 1) NEWID())
FROM 
(SELECT 1 id UNION ALL SELECT 2 ) a
...
Рейтинг: 0 / 0
15.01.2018, 16:08
    #39584547
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
или через джоин если хочется

Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT 
	*
FROM 
(SELECT 1 id UNION ALL SELECT 2 ) a
LEFT JOIN
(SELECT TOP (SELECT 1) NEWID() x) b
ON 1 = 1
...
Рейтинг: 0 / 0
15.01.2018, 16:09
    #39584550
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
TaPaK,

Большое спасибо, так работает, но в голове не очень помещается.
Что такое TOP (SELECT 1) - это какая-то недекларированная фича? План запроса отличается кардинально. Очень бы хотелось узнать о такой конструкции подробнее.
...
Рейтинг: 0 / 0
15.01.2018, 16:14
    #39584554
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Я имею в виду различия плана вот с таким запросом:

Код: sql
1.
2.
3.
4.
SELECT a.id,
	(SELECT TOP (1) NEWID())
FROM 
(SELECT 1 id UNION ALL SELECT 2 ) a



А вот такой запрос всё равно не работает:

Код: sql
1.
2.
3.
4.
SELECT x.n, a.id
  FROM (SELECT TOP (SELECT 1) NEWID() n) x
  JOIN (SELECT 1 id UNION ALL SELECT 2) a
    ON 1=1



Есть ощущение что это какие-то игры оптимизатора и на какой-нибудь версии sql-сервера это всё перестанет работать (а возможно и сейчас не везде работает, проверял только на 2008 и 2014). Хотелось бы какую то теоретическую базу понять.
...
Рейтинг: 0 / 0
15.01.2018, 16:16
    #39584558
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Drunik,

я же написал "но это вроде баг"
сейячас работает вплоть до 2016. Используйте переменную
...
Рейтинг: 0 / 0
15.01.2018, 16:19
    #39584563
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
TaPaK,

Я понял, спасибо, будем знать.
...
Рейтинг: 0 / 0
15.01.2018, 16:26
    #39584572
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Drunik,

Код: sql
1.
2.
3.
SELECT a.n, a.id
  FROM (SELECT NEWID() n) x cross apply
  (SELECT x.n, 1 id UNION ALL SELECT x.n, 2) a


DrunikЕсть ощущение что это какие-то игры оптимизатораАга, игры.
Сравните планы вашего запроса и моего. И обратите внимание где и сколько раз вычисляется newid().
...
Рейтинг: 0 / 0
15.01.2018, 17:30
    #39584622
ATI.HeNRy
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
First_value(newid()) over(order by (select null))
Если лень.
...
Рейтинг: 0 / 0
15.01.2018, 19:07
    #39584668
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
invmDrunik,

Код: sql
1.
2.
3.
SELECT a.n, a.id
  FROM (SELECT NEWID() n) x cross apply
  (SELECT x.n, 1 id UNION ALL SELECT x.n, 2) a


DrunikЕсть ощущение что это какие-то игры оптимизатораАга, игры.
Сравните планы вашего запроса и моего. И обратите внимание где и сколько раз вычисляется newid().

Сломался ваш запрос на чуть более реальном примере:

Код: sql
1.
2.
3.
SELECT a.n, a.id
  FROM (SELECT NEWID() n) x 
 CROSS apply (SELECT x.n, id=number FROM master.dbo.spt_values WHERE type='P' AND number BETWEEN 1 AND 10) a



Вобщем Бог с ним с этим гуидом, не ломайте голову коллеги, я свои проблемы решил добавлением переменой - просто и надёжно.
...
Рейтинг: 0 / 0
15.01.2018, 19:35
    #39584682
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
DrunikСломался ваш запрос на чуть более реальном примереПеременная конечно надежнее. А если понадобится, например, запихнуть сей запрос в инлайновую функцию?

Суть решения - обязательная зависимость в cross apply результата внутреннего запроса от внешнего.
А в вашем чуть более реальном примере это не так.

Более правильный вариант:
Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT x.n, a.id
  FROM (SELECT NEWID() n) x cross apply
  (SELECT 1 id UNION ALL SELECT 2 where x.n >= 0x0) a
  
SELECT a.n, a.id
  FROM (SELECT NEWID() n) x 
 CROSS apply (SELECT x.n, id=number FROM master.dbo.spt_values WHERE type='P' AND number BETWEEN 1 AND 10 and x.n >= 0x0) a
...
Рейтинг: 0 / 0
15.01.2018, 22:55
    #39584730
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
invmСуть решения - обязательная зависимость в cross apply результата внутреннего запроса от внешнего.
А в вашем чуть более реальном примере это не так.

Уважаемый invm, это всё отлично и про инлайновые функции и вьюхи вы абсолютно правы - в жизни всё требуется, но вы это где-то всё прочитали, в какой-то документации или это всё на уровне шаманства и танцев с бубнами? Интерес действительно не праздный, т.к. кроме гуидов часто встречаются запросы с обращением к какой-нибудь инлайн функции, которая вполне могла бы вызваться 1 раз, но вызывается как назло по кол-ву строк в запросе, например что то вроде такого:

Код: sql
1.
2.
declare @d datetime = getdate()
select * from Table1 where field1>dbo.func1(@d)



В такого рода запросах (более сложных) оптимизатор вдруг может делать множество обращений к func1. Если вы могли бы дать какие-то общие рекомендации, правила как этого избежать, то это, думаю, было бы полезно для многих. Конечно очень желательно всё это подкрепить какими то ссылками на документацию или статьи. Не хотелось бы при необходимости перехода на новую версию sql-сервера рвать на всех местах волосы по причине необходимости переписывания половины объектов в БД из-за того, что такая конструкция перестанет работать. В любом случае спасибо за информацию.
...
Рейтинг: 0 / 0
16.01.2018, 10:54
    #39584898
Гигабайт Мегабайтович Килобайтов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Drunik,

знать как работает sql-сервер, а именно читать справку, ходить на курсы ))
...
Рейтинг: 0 / 0
16.01.2018, 11:05
    #39584910
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Гигабайт Мегабайтович КилобайтовDrunik,

знать как работает sql-сервер, а именно читать справку, ходить на курсы ))

Уважаемый Гигабайт Мегабайтович, а зачем тогда нужен форум? Всё же можно прочитать в справке и походить на курсы? Я думал он нужен для обмена знаниями, видимо ошибался? Кто решает какие можно задавать вопросы на форуме, а какие нельзя? Вы?
...
Рейтинг: 0 / 0
16.01.2018, 11:11
    #39584917
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Drunik,

простой ответ: не используйте скалярки в WHERE и тчк :)
...
Рейтинг: 0 / 0
16.01.2018, 11:12
    #39584920
Гигабайт Мегабайтович Килобайтов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
DrunikГигабайт Мегабайтович КилобайтовDrunik,

знать как работает sql-сервер, а именно читать справку, ходить на курсы ))

Уважаемый Гигабайт Мегабайтович, а зачем тогда нужен форум? Всё же можно прочитать в справке и походить на курсы? Я думал он нужен для обмена знаниями, видимо ошибался? Кто решает какие можно задавать вопросы на форуме, а какие нельзя? Вы?
ну если вы хотите на форуме про льва толстого что-бы вам процитировать всю "войну и мир " то что вы ожидаете в ответ услышать?
а что можно и что нельзя - есть в правилах форума. И также в рекомендациях.
...
Рейтинг: 0 / 0
16.01.2018, 11:15
    #39584922
TaPaK
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Гигабайт Мегабайтович Килобайтов,

плохо что нет рекомендации "не пуустозвонить"
...
Рейтинг: 0 / 0
16.01.2018, 11:21
    #39584924
Drunik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
TaPaKГигабайт Мегабайтович Килобайтов,

плохо что нет рекомендации "не пуустозвонить"

Поддерживаю полностью.
TaPaK, спасибо за рекомендации!
...
Рейтинг: 0 / 0
16.01.2018, 11:48
    #39584943
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Drunik,

если функция indeterministic, то сервер вынужден выполнить вызов ее для каждой строки. Т.е. функция при том же аргументе вернет другое значение. В том числе это системные функции даты-времени (rowguid также функция даты-времени).

Если правильно помню, то в некоторых случаях скалярную функцию можно привязать к схеме и они станет deterministic и запрос вычислит ее один раз.

Может это мои фантазии, надо проверять :)
...
Рейтинг: 0 / 0
16.01.2018, 12:09
    #39584960
Ролг Хупин
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
Гигабайт Мегабайтович КилобайтовDrunikпропущено...


Уважаемый Гигабайт Мегабайтович, а зачем тогда нужен форум? Всё же можно прочитать в справке и походить на курсы? Я думал он нужен для обмена знаниями, видимо ошибался? Кто решает какие можно задавать вопросы на форуме, а какие нельзя? Вы?
ну если вы хотите на форуме про льва толстого что-бы вам процитировать всю "войну и мир " то что вы ожидаете в ответ услышать?
а что можно и что нельзя - есть в правилах форума. И также в рекомендациях.

при всех недостатках ТС в данной теме - разве он просил "процитировать войну и мир" или всю документацию?
...
Рейтинг: 0 / 0
16.01.2018, 12:12
    #39584964
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как получить одинаковый GUID
DrunikИнтерес действительно не праздный, т.к. кроме гуидов часто встречаются запросы с обращением к какой-нибудь инлайн функции, которая вполне могла бы вызваться 1 раз, но вызывается как назло по кол-ву строк в запросеВы путаете инлайновую со скалярной.
DrunikВ такого рода запросах (более сложных) оптимизатор вдруг может делать множество обращений к func1Это зависит от детерминированности функции, формы запроса и оптимизатора.
Пример
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
use tempdb;
go

create function dbo.fn1
(
 @x int
)
returns varchar(200)
as
begin
 return (select name from sys.objects where object_id = @x);
end;
go

create function dbo.fn2
(
 @x int
)
returns varchar(200)
as
begin
 return 'x = ' + cast(@x as varchar(10));
end;
go

create function dbo.fn3
(
 @x int
)
returns varchar(200)
with schemabinding
as
begin
 return 'x = ' + cast(@x as varchar(10));
end;
go

select objectproperty(object_id, 'IsDeterministic'), name from sys.objects where name in (N'fn1', N'fn2', N'fn3') and schema_name(schema_id)  = N'dbo';
go

select top (5) * into #t from master.dbo.spt_values;
go

set statistics xml on;

/*5 раз*/select * from #t where name = dbo.fn1(1);
/*5 раз*/select * from #t where name = dbo.fn2(1);
/*1 раз*/select * from #t where name = dbo.fn3(1);
/*1 раз*/select * from #t where name = (select dbo.fn1(1));
/*1 раз*/select * from #t where name = (select dbo.fn2(1));

declare @x int = 1;

/*5 раз*/select * from #t where name = dbo.fn1(@x);
/*5 раз*/select * from #t where name = dbo.fn2(@x);
/*1 раз*/select * from #t where name = dbo.fn3(@x);
/*5 раз*/select * from #t where name = (select dbo.fn1(@x));
/*5 раз*/select * from #t where name = (select dbo.fn2(@x));
/*1 раз*/select * from #t where name = (select dbo.fn1(@x)) option (recompile);
/*1 раз*/select * from #t where name = (select dbo.fn2(@x)) option (recompile);

set statistics xml off;
go

drop table #t;
drop function dbo.fn1, dbo.fn2, dbo.fn3;
go

...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как получить одинаковый GUID / 25 сообщений из 27, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]