powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Нужна помощь с рекурсией
10 сообщений из 10, страница 1 из 1
Нужна помощь с рекурсией
    #40052158
Ramis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте, есть таблица со связанными ИД, пытаюсь через рекурсию связать их в группы. Но что то не могу правильно написать условие в запросе, что бы уйти от зацикливания и получения групп

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
INSERT INTO #t (Id_1, Id_2)
VALUES 
	(1, 2),	(1, 3),	(1, 4),	(4, 2),	(5, 6),	(6, 7),	(5, 10), (8, 9),
	(2, 1),	(3, 1),	(4, 1),	(2, 4),	(6, 5),	(7, 6),	(10, 5), (9, 8);

DECLARE @ID INT;
--SET @ID = 1

;WITH cte AS
(
  SELECT Id_1, Id_2, 0 AS lvl FROM #t WHERE Id_1 = @ID OR @ID IS NULL
  UNION ALL  
  SELECT t.Id_1, t.Id_2, c.lvl+1
  FROM #t  t 
  JOIN cte c ON c.Id_2 = t.Id_1
  --WHERE NOT EXISTS (SELECT 1 FROM #t WHERE t.Id_2 = c.Id_1 AND t.Id_1 = c.Id_2 )
  --and c.lvl in (1,2,3)
) 
SELECT Id_1, Id_2, lvl
FROM cte 
ORDER BY lvl
OPTION (MAXRECURSION 100)



В результате хотелось бы получить
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
group	Id_1	Id_2
A	1	2
A	1	3
A	1	4
A	4	2
B	5	6
B	5	10
B	6	7
C	8	9
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052160
Ramis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Microsoft SQL Server 2012 - 11.0.2100.60 (X64) Feb 10 2012 19:39:15 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052164
Агрох
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
INSERT INTO #t (Id_1, Id_2)
VALUES 
	(1, 2),	(1, 3),	(1, 4),	(4, 2),	(5, 6),	(6, 7),	(5, 10), (8, 9),
	(2, 1),	(3, 1),	(4, 1),	(2, 4),	(6, 5),	(7, 6),	(10, 5), (9, 8);



Получается что указатель один ссылается на указатель 2, указатель 2 ссылается на указатель 1, который в свою очередь ссылается на указатель 2, который ссылается на указатель 1....
Да, тут будет бесконечное зацикливание, т.к. оно предусмотрено исходными данными.

Либо убери вторую строчку из VALUES либо подумай над тем, как ещё ограничить вложенность.
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052182
Ramis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Агрох,
Если убрать вторую строку в VALUE, и запустить указав @ID =2 то ни чего не найдется.

если дописать условие
Код: sql
1.
 SELECT Id_1, Id_2, 0 AS lvl FROM #t WHERE Id_1 = @ID OR Id_2 = @ID OR @ID IS NULL



то получим результат где с 1 мы не вышли на 3:
1 2
4 2
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052192
Агрох
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ramis, что такое @ID?
Если тебе надо вывести всю группу, даже если родитель ссылается на несуществующий объект - по которому ты и ищещь, то надо в условии прописывать что то типа: Id_1 = @ID or Id_2 = @ID.
Ещё раз, сейчас исходные данные сами по себе предполагают бесконечное зацикливание. Да ещё и, насколько я понял, ты роль Id_1 и Id_2 просто меняешь местами, т.к. по структуре выглядит всё так, что Id_2 - идентификатор элемента, а Id_1 - идентификатор родителя.
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052193
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
;WITH cte AS
(
  SELECT Id_1, Id_2, 0 AS lvl, '(' + cast(Id_1 as varchar(max)) + ')' as p FROM @t WHERE Id_1 = @ID OR @ID IS NULL
  UNION ALL  
  SELECT t.Id_1, t.Id_2, c.lvl+1, c.p + a.p
  FROM #t  t 
  JOIN cte c ON c.Id_2 = t.Id_1 cross apply
  (select '(' + cast(t.Id_1 as varchar(10)) + ')') a(p)
  where
   c.p not like '%' + a.p + '%'
) 
SELECT Id_1, Id_2, lvl, p
FROM cte 
ORDER BY lvl
OPTION (MAXRECURSION 100);
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052219
Ramis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,
Спасибо большое. А как нибудь еще группы можно вывести?
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052228
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ramis
А как нибудь еще группы можно вывести?

Код: 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.
;with cte as (
	select 
		t1.Id_1 as GrId 
		,t1.Id_1 
		,t1.Id_2 
		,cast('/'+cast(t1.Id_1 as varchar)+'/'+cast(t1.Id_2 as varchar)+'/' as varchar(max)) as path
	from #t t1
	where not exists(select 1 from #t t2 where t1.Id_1=t2.Id_2 and t1.Id_1>t2.Id_1)

	union all

	select
		cte.GrId
		,t1.Id_1
		,t1.Id_2
		,cte.path+cast(t1.Id_2 as varchar)+'/' as path
	from cte inner join #t t1 on cte.Id_2=t1.Id_1
	where cte.path not like '%/'+cast(t1.Id_2 as varchar)+'/%'
)
select 
	char(dense_rank()over(order by GrId)-1+ascii('A')) as Gr
	,Id_1
	,Id_2
from cte order by 1,2,3


GrId_1Id_2A12A13A14A24A42B56B510B67C89
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052269
Ramis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,
спасибо, но если запускать по определенному @ID, то отрабатывает не верно
...
Рейтинг: 0 / 0
Нужна помощь с рекурсией
    #40052543
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ramis
court,
спасибо, но если запускать по определенному @ID, то отрабатывает не верно


если запускать "по определенному @ID", то непонятно про какие группы ты рассказываешь, так как это и будет одна группа (граф)

пс
я делал исходя из предположения, что у тебя несколько ненаправленных графов, так как выглядят исх.данные в сабже
и нужно разделить точки дуги по этим графам (группам) - так как выглядит "желаемый результат"
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Нужна помощь с рекурсией
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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