powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Поиск цикла по иерархической структуре
6 сообщений из 6, страница 1 из 1
Поиск цикла по иерархической структуре
    #40097554
newbie876454
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
сделал такой скрипт для поиска циклов в иерархической структуре
как бы его ускорить, чтобы не проходить дважды один и тот же путь от разных начальных узлов?
а то не оптимально получается, и к тому же несколько раз один и тот же цикл выводится

знаю, что можно сделать процедурой в виде цикла, но не хотелось заморачиваться и перебивать алгоритм на новые рельсы
к тому же дебаг процедур в SSMS осложнен тем, что в новых версиях убрали отладчик
хотелось бы по возможности допилить это простое решение


Код: 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.
IF OBJECT_ID('dbo.TAB1') IS NOT NULL
	DROP TABLE dbo.TAB1

CREATE TABLE TAB1 (
	COLUMN11 NVARCHAR(10) NOT NULL,
	COLUMN12 NVARCHAR(10) NOT NULL,
	COLUMN21 NVARCHAR(10) NOT NULL,
	COLUMN22 NVARCHAR(10) NOT NULL,
	PRIMARY KEY CLUSTERED (COLUMN11, COLUMN12, COLUMN21, COLUMN22)
)

INSERT INTO TAB1
VALUES 
('111', '01', '111', '02'),
('111', '02', '111', '03'),
('111', '03', '222', '01'),
('222', '01', '222', '02'),
('222', '02', '111', '02'),
('333', '01', '333', '02'),
('333', '02', '333', '03'),
('333', '03', '333', '01')

go

;WITH CYCLE AS (
	SELECT DISTINCT 
		COLUMN11 AS beg1,
		COLUMN12 AS beg2,
		CONVERT(NVARCHAR(MAX), '\' + COLUMN11 + '_' + COLUMN12 + '\') AS pth, 
		0 AS repeats
	FROM TAB1

	UNION ALL
		
	SELECT
		nx.COLUMN11 AS beg1, 
		nx.COLUMN12 AS beg2, 
		cur.pth + nx.COLUMN11 + '_' + nx.COLUMN12 + '\' AS pth,
		(
			CASE
				WHEN CHARINDEX('\' + nx.COLUMN11 + '_' + nx.COLUMN12 + '\', cur.pth) > 0
					THEN cur.repeats + 1
				ELSE cur.repeats
			END
		) AS repeats
	FROM cycle AS cur 
	JOIN TAB1 AS nx
		ON cur.beg1 = nx.COLUMN21
		AND cur.beg2 =  nx.COLUMN22
	WHERE cur.repeats < 1
)
SELECT pth AS CyclePaths
FROM cycle
WHERE repeats = 1
ORDER BY LEN(PTH)
OPTION (MAXRECURSION 0)
...
Рейтинг: 0 / 0
Поиск цикла по иерархической структуре
    #40097586
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Поиск цикла по иерархической структуре
    #40097588
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник

Там забыли объяснить как исключить повторные циклы.
Тредстартер хочет не только "факт наличия цикла", но "сам цикл в единственном экземпляре".
ВашЪ КО.
...
Рейтинг: 0 / 0
Поиск цикла по иерархической структуре
    #40097637
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вселенский тормоз.
Код: 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.
IF OBJECT_ID('dbo.TAB1') IS NOT NULL
	DROP TABLE dbo.TAB1

CREATE TABLE TAB1 (
	COLUMN11 NVARCHAR(10) NOT NULL,
	COLUMN12 NVARCHAR(10) NOT NULL,
	COLUMN21 NVARCHAR(10) NOT NULL,
	COLUMN22 NVARCHAR(10) NOT NULL,
    id int identity unique,
	PRIMARY KEY CLUSTERED (COLUMN11, COLUMN12, COLUMN21, COLUMN22)
)

INSERT INTO TAB1
VALUES 
('111', '01', '111', '02'),
('111', '02', '111', '03'),
('111', '03', '222', '01'),
('222', '01', '222', '02'),
('222', '02', '111', '02'),
('333', '01', '333', '02'),
('333', '02', '333', '03'),
('333', '03', '333', '01')

go

;WITH c AS ( SELECT id, 0 AS cnt, Cycle = cast(0 as bit), COLUMN11 AS beg1, COLUMN12 AS beg2 FROM TAB1
             UNION ALL
            SELECT c.id, c.cnt + 1 as cnt, Cycle = cast(iif(c.id = n.id, 1, 0) as bit), n.COLUMN11 AS beg1, n.COLUMN12 AS beg2
                FROM c 
                JOIN TAB1 AS n on c.beg1 = n.COLUMN21 AND c.beg2 = n.COLUMN22
                WHERE c.Cycle = 0
    )
    , ac as ( SELECT * FROM c where exists( select * from c as x where x.id = c.id and x.Cycle = 1 ) )
  select * from ac
    where not exists( select * from ac as x where x.id < ac.id 
                                    and not exists(select beg1, beg2 from ac as y where id = x.id except select beg1, beg2 from ac as y where id = ac.id) 
                                    and not exists(select beg1, beg2 from ac as y where id = ac.id except select beg1, beg2 from ac as y where id = x.id)
                      )
    ORDER BY id, cnt
...
Рейтинг: 0 / 0
Поиск цикла по иерархической структуре
    #40097643
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
newbie876454,

Вот здесь есть пример защиты от зацикливания в рекурсии.

https://www.sql.ru/forum/1322566/rekursiya-s-dublyami
...
Рейтинг: 0 / 0
Поиск цикла по иерархической структуре
    #40097675
newbie876454
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо.
интересный метод с битмапом, не знал о таком
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Поиск цикла по иерархической структуре
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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