Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 функция в подзапросе выполняется вне самого подзапроса, почему так происходит?  [new]
Подзапрос
Guest
Пытался сгруппировать данные, но получилось только в варианте 2 - поле [group] уникальное только в пределах одной группы, как и надо, в варианте 1 уже не получается - [group] уникально в пределах всей таблицы. Объясните так должно быть и почему?
Всегда считал, что подзапрос можно рассматривать как готовую временную таблицу, а тут получается, что функция выноситься во внешний запрос и выполняется для каждой записи внешнего запроса.

ps Microsoft SQL Server 2005

/*	Подготовка данных	*/

declare
	@idList xml
set	@idList = '
	<root>
		<parent_id>1</parent_id>
		<r><id>1</id><id>2</id><id>3</id></r>
	</root>
	<root>
		<parent_id>12</parent_id>
		<r><id>7</id><id>8</id><id>9</id></r>
	</root>
	<root>
		<parent_id></parent_id>
		<r><id>45</id><id>4545</id></r>
	</root>
	<root>
		<r><id>77</id><id>7777</id><id>77777</id></r>
	</root>
	<root>
		<r><id>88</id><id>8888</id><id>88</id></r>
	</root>
	'

/*	вариант 1	*/
select
	t.parent_id, tlist.id, t.[group]
from (
	select
		isnull(cd.r.value('parent_id[1]', 'int'), 0) as parent_id,
		cd.r.query('r') as idList,
		newid() as [group]
	from @idList.nodes('root') as cd(r)
) t
cross apply (
	select
		cd.r.value('.[1]', 'int') as id
	from t.idList.nodes('/r/id') as cd(r)
) tlist


/*	вариант 2	*/
declare @t table (parent_id int, idList xml, [group] uniqueidentifier)

insert into @t (parent_id, idList, [group])
select
	isnull(cd.r.value('parent_id[1]', 'int'), 0) as parent_id,
	cd.r.query('r') as idList,
	newid() as [group]
from @idList.nodes('root') as cd(r)

select
	t.parent_id, tlist.id, t.[group]
from @t t
cross apply (
	select
		cd.r.value('.[1]', 'int') as id
	from t.idList.nodes('/r/id') as cd(r)
) tlist
19 июн 15, 09:24    [17790891]     Ответить | Цитировать Сообщить модератору
 Re: функция в подзапросе выполняется вне самого подзапроса, почему так происходит?  [new]
gang
Member

Откуда:
Сообщений: 1394
Подзапрос,

Это "особенности" некоторых недетерминированных функций. См., например, тут , тут или тут
19 июн 15, 10:57    [17791294]     Ответить | Цитировать Сообщить модератору
 Re: функция в подзапросе выполняется вне самого подзапроса, почему так происходит?  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7868
подзапрос можно рассматривать как готовую временную таблицу

Абсолютно неверно.
19 июн 15, 11:05    [17791341]     Ответить | Цитировать Сообщить модератору
 Re: функция в подзапросе выполняется вне самого подзапроса, почему так происходит?  [new]
gang
Member

Откуда:
Сообщений: 1394
Владислав Колосов
подзапрос можно рассматривать как готовую временную таблицу

Абсолютно неверно.

+1. В общем-то то, что Вы написали в своем запросе для сервера только "хотелки". Решение о том, что, как и когда реально выполнять он принимает сам, по результатам работы "у его внутре думательной машины" - оптимизатора.
19 июн 15, 11:09    [17791371]     Ответить | Цитировать Сообщить модератору
 Re: функция в подзапросе выполняется вне самого подзапроса, почему так происходит?  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
Подзапрос
а тут получается, что функция выноситься во внешний запрос и выполняется для каждой записи внешнего запроса.
Оптимизатор имеет право так делать, потому что у вас newid никак не коррелирует с cross apply и поэтому от места вычисления newid семантика запроса не зависит.
Обмануть можно, например, так:
select
	t.parent_id, tlist.id, t.[group]
from (
	select
		isnull(cd.r.value('parent_id[1]', 'int'), 0) as parent_id,
		cd.r.query('r') as idList,
		newid() as [group]
	from @idList.nodes('root') as cd(r)
) t
cross apply (
	select
		cd.r.value('.[1]', 'int') as id
	from t.idList.nodes('/r/id') as cd(r)
    where t.[group] >= 0x0
) tlist
19 июн 15, 11:16    [17791410]     Ответить | Цитировать Сообщить модератору
 Re: функция в подзапросе выполняется вне самого подзапроса, почему так происходит?  [new]
Подзапрос
Guest
спасибо всем, стало понятно
invm,
так делать не буду, т.к. могут обратно переделать (убрать "лишнее" условие) и все станет на "свои" места
лучше явно использовать времянку, хотя тоже нет гарантии чтj не "оптимизируют"
19 июн 15, 11:28    [17791469]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить