Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

Откуда:
Сообщений: 414
Уважаемые форумчане подскажите. Существует схема приложенная в рисунке, как выбрать все связанные карточки, так чтобы рекурсия не заклилась в случае если в таблице TCardsInCards будут значения допустим 2,3 и 3,2. Че то мозги уже как сама рекурсия запутались.

К сообщению приложен файл. Размер - 27Kb
9 фев 12, 20:45    [12065927]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31986
AlexHome
Уважаемые форумчане подскажите. Существует схема приложенная в рисунке, как выбрать все связанные карточки, так чтобы рекурсия не заклилась в случае если в таблице TCardsInCards будут значения допустим 2,3 и 3,2. Че то мозги уже как сама рекурсия запутались.
Рекурсию делают, например, с помощью CTE (посмотрите в BOL, там есть пример), а зацикливания можно избежать, добавив проверку not exists
9 фев 12, 21:35    [12066074]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

Откуда:
Сообщений: 414
Да вот и делал с помощью CTE что запутался
9 фев 12, 21:59    [12066118]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

Откуда:
Сообщений: 414
WITH RecursiveTable(IDCard,CardName,IDCardParent,IDCardChild) AS ( 
SELECT TCards.IDCard,TCards.CardName,IDCardParent,IDCardChild FROM TCards,TCardsInCards where TCards.IDCard=TCardsInCards.IDCardParent 
and idcard=11
UNION ALL  
SELECT TCards.IDCard,TCards.CardName,e.IDCardParent,e.IDCardChild FROM TCards,TCardsInCards e  
INNER JOIN RecursiveTable ecte ON ecte.IDCardChild = e.IDCardParent
and not exists(select IDCardParent from TCardsInCards where IDCardParent=IDCardChild)
)  
SELECT *  
FROM RecursiveTable order by CardName


вот что здесь и как подправить
9 фев 12, 22:01    [12066124]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
iljy
Member

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

храните на каждой итерации путь в виде строки, соответственно на следующей итерации проверяйте вхождение.
9 фев 12, 22:01    [12066125]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

Откуда:
Сообщений: 414
iljy
AlexHome,

храните на каждой итерации путь в виде строки, соответственно на следующей итерации проверяйте вхождение.

вот щас точно мозг лопнет, че за путь и в какой строке?????
9 фев 12, 22:05    [12066139]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
iljy
Member

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

declare @t table (id int, idparent int)
insert @t values
(1,null),
(2,1),
(3,1),
(4,2),
(5,2)

;with cte as
(
	select id, id idparent, CAST(id as varchar(8000)) path
	from @t
	where idparent is null
		union all
	select t.id, c.idparent, path + '-' + CAST(t.id as varchar)
	from cte c join @t t on c.id = t.idparent
)
select * from cte
9 фев 12, 22:12    [12066158]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

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

Спасибо, щас пар сек проверю
9 фев 12, 22:14    [12066160]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

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

Просто офигенно, все работает еще раз большое спасибо
9 фев 12, 22:17    [12066171]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

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

Хотя нет не все так хорошо при добавлении еще одного значения (2,5), улетает в бесконечный цыкл
declare @t table (id int, idparent int)
insert @t values
(1,null),
(2,1),
(3,1),
(4,2),
(5,2),
[b](2,5)[/b]

;with cte as
(
	select id, id idparent, CAST(id as varchar(8000)) path
	from @t
	where idparent=2
		union all
	select t.id, c.idparent, path + '-' + CAST(t.id as varchar)
	from cte c join @t t on c.id = t.idparent
)
select * from cte
9 фев 12, 22:22    [12066186]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
iljy
Member

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

так проверку-то добавьте!
9 фев 12, 22:24    [12066194]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

Откуда:
Сообщений: 414
AlexHome
iljy,

Хотя нет не все так хорошо при добавлении еще одного значения (2,5), улетает в бесконечный цыкл
declare @t table (id int, idparent int)
insert @t values
(1,null),
(2,1),
(3,1),
(4,2),
(5,2),
[b](2,5)[/b]

;with cte as
(
	select id, id idparent, CAST(id as varchar(8000)) path
	from @t
	where idparent=2
		union all
	select t.id, c.idparent, path + '-' + CAST(t.id as varchar)
	from cte c join @t t on c.id = t.idparent
)
select * from cte


и какой резон этой строки че-то не доганю
9 фев 12, 22:25    [12066197]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

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

Подскажи че-то мозги уже плавятся не доганю куда проверку добавить
9 фев 12, 22:26    [12066199]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
iljy
Member

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

declare @t table (id int, idparent int)
insert @t values
(1,null),
(2,1),
(3,1),
(4,2),
(5,2),
(2,5)

;with cte as
(
	select id, id idparent, '-' + CAST(id as varchar(8000)) path
	from @t
	where idparent is null
		union all
	select t.id, c.idparent, path + '-' + CAST(t.id as varchar)
	from cte c join @t t on c.id = t.idparent
		and path not like '%-' + CAST(t.id as varchar(8000)) + '%'
)
select * from cte
9 фев 12, 22:28    [12066204]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
AlexHome
Member

Откуда:
Сообщений: 414
iljy
AlexHome,

declare @t table (id int, idparent int)
insert @t values
(1,null),
(2,1),
(3,1),
(4,2),
(5,2),
(2,5)

;with cte as
(
	select id, id idparent, '-' + CAST(id as varchar(8000)) path
	from @t
	where idparent is null
		union all
	select t.id, c.idparent, path + '-' + CAST(t.id as varchar)
	from cte c join @t t on c.id = t.idparent
		and path not like '%-' + CAST(t.id as varchar(8000)) + '%'
)
select * from cte


огромнейшее спасибо, щас буду разбираться что к чему здесь, все отлично работает
9 фев 12, 22:30    [12066210]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
dolf85
Member

Откуда:
Сообщений: 58
Здравствуйте
не могли бы вы подсказать, как вывести всю ветку? имеется Человек1(id=1, parentid=1), Человек2(id=2, parentid=1), Человек3(id=3, parentid=2) и т.д. Как вывести весь список, начиная с верхнего?
28 май 12, 13:06    [12625356]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
pegoopik
Member

Откуда: Новосибирск
Сообщений: 54
dolf85,

Да почти так же как и в предыдущем примере.

declare @Tree table(id int, idparent int)
insert @Tree values
(1,null),
(2,1),
(3,2),
(4,7),
(5,2),
(2,2),
(7,4)

;
/*
вообще говоря, если рекурсия проводится не над таблицей, а над вьюхой,
то её надо либо записать во времянку либо хотя бы сделать насильственный спул:
*/
with SpoolTree as
(select 0tmp,* from @Tree union all select * from SpoolTree where tmp>0)
/*
здесь он на фиг не нужен, поставил просто для примера
в одной задачке с sql-ex. такое действо уменьшило время выполнения с 1,328 до 0,234 
*/
,cte as
(
  select t.id, t.idparent, cast('-'as varchar(8000))str
  from SpoolTree t
  where t.id = 1--выбираем начало ветки

  union all
  
  select t.id, t.idparent, cast(str+'-'+cast(cte.id as varchar)as varchar(8000))
  from cte, SpoolTree t
  where cte.id = t.idparent
    and Str not like '%-'+cast(cte.id as varchar)+'%'

)

select id, idparent from cte

option (maxrecursion 0)
28 май 12, 14:17    [12625810]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
dolf85
Member

Откуда:
Сообщений: 58
а откуда берется:
28 май 12, 14:28    [12625933]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
dolf85
Member

Откуда:
Сообщений: 58
а откуда берется:
insert @Tree values
(1,null),
(2,1),
(3,2),
(4,7),
(5,2),
(2,2),
(7,4)
у меня нет данных по id, их очень много,
просто просмотреть данные могу так:
select * from Subdealers where subdealerid=238, получаю результат:
subdealerid=238, name='Человек1', parentid=1, и вот у того Человек1 есть большая ветка, нет ли возможности, чтобы просматривал и выводил дерево всех, кто под 238? в оракле делаю примерно так:
SELECT LPAD(' ', 3 * level) || DEALERNAME, DEALERID
FROM KP_DEALER.DEALER d, KP_DEALER.KPDACCOUNT a
where a.ACCOUNTNUM=d.ACCOUNTNUM
START WITH d.accountnum=999344912
CONNECT BY dealerid = PRIOR parentid
ORDER SIBLINGS BY DEALERNAME;
28 май 12, 14:34    [12625989]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
pegoopik
Member

Откуда: Новосибирск
Сообщений: 54
dolf85,

В чем проблема-то?
declare @Tree table(id int, idparent int, name varchar(25))
insert @Tree values
  select subdealerid, parentif, name from Subdealers 

;with cte as
(
  select t.id, t.idparent, t.name, cast('-'as varchar(8000))str
  from @Tree t
  where t.id=238

  union all
  
  select t.id, t.idparent, t.name, cast(str+'-'+cast(cte.id as varchar)as varchar(8000))
  from cte, @Tree t
  where cte.id = t.idparent
    and Str not like '%-'+cast(cte.id as varchar)+'%'
)
select id, idparent, name from cte
option (maxrecursion 0)

Повторюсь. Поместил во временную таблицу, чтобы не пересчитывалась каждый раз. Может быть вам этого не надо. Тогда просто замените @Tree на Subdealers и переменуйте поля.
28 май 12, 14:45    [12626079]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
dolf85
Member

Откуда:
Сообщений: 58
простите, но что-то торможу и в упор не понимаю, сделал так:
with cte as
(
select s.SubdealerId, s.ParentID , s.[Name] , cast('-'as varchar(8000))str
from Subdealers s
where s.SubdealerId=238

union all

select s.SubdealerId, s.ParentID , s.[Name] , cast(str+'-'+cast(cte.id as varchar)as varchar(8000))
from Subdealers s
where cte.id = s.ParentID
and Str not like '%-'+cast(cte.id as varchar)+'%'
)
select id, idparent, name from cte
option (maxrecursion 0)

ругается на "where cte.id = s.ParentID" - the multi-part identifier "cte.id" could not be bpund
28 май 12, 16:56    [12627171]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
dolf85
Member

Откуда:
Сообщений: 58
select s.SubdealerId, s.ParentID , s.[Name] , cast(str+'-'+cast(cte.id as varchar)as varchar(8000))
from cte, Subdealers s
where cte.id = s.ParentID
and Str not like '%-'+cast(cte.id as varchar)+'%' - invalid object cte
28 май 12, 17:20    [12627363]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
dolf85
the multi-part identifier "cte.id" could not be bpund
Если вы не понимаете буржуйского есть переводчик.
И настройте у своего пользователя в БД язык по умолчанию, родной вам.
28 май 12, 17:25    [12627397]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
dolf85
Member

Откуда:
Сообщений: 58
эту ошибку уже исправил, появилась вторая)))
28 май 12, 17:27    [12627415]     Ответить | Цитировать Сообщить модератору
 Re: Рекурсивный запрос многие ко многим  [new]
pegoopik
Member

Откуда: Новосибирск
Сообщений: 54
dolf85,

select s.SubdealerId as Id, ...
28 май 12, 19:16    [12628040]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить