powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Найти последнего потомка.
10 сообщений из 35, страница 2 из 2
Найти последнего потомка.
    #39942338
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Earl11
alexeyvg
Нужно к нему добавить TOP 1, с сортировкой CHAIN DESC

В конечный SELECT? или тот, что в рекурсии?
В конечный.

Это же так просто: вы получили список узлов, с строкой - полным путём к элементу (CHAIN).
Последняя строка, если список отсортировать по этой строке - это последний элемент.
Один последний элемент в сортированным списке можно получить SELECT TOP 1 ... ORDER BY поле сортировки DESC
Earl11
aleks222Это делается в один тривиальный запрос.

Какой?)Да, присоединяюсь. Учитывая, что зацикливание может быть не тупое, как тут, а из нескольких элементов.
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942348
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
select * from Таблица as t1 where not exists( select * from Таблица as t2 where t2.Член = t1.Потомок)
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942376
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleks222
Код: sql
1.
select * from Таблица as t1 where not exists( select * from Таблица as t2 where t2.Член = t1.Потомок)

Даже на простом зацикливании не покажет (на данных автора).
Про сложное я даже не говорю.
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942392
Earl11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexeyvg

Это же так просто: вы получили список узлов, с строкой - полным путём к элементу (CHAIN).
Последняя строка, если список отсортировать по этой строке - это последний элемент.
Один последний элемент в сортированным списке можно получить SELECT TOP 1 ... ORDER BY поле сортировки DESC

Согласен. Не точно выразился. Если взять больше данных и связей...в общем, вывести конечного ребёнка каждого родителя таким способом не получится)
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942453
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Earl11
alexeyvg

Это же так просто: вы получили список узлов, с строкой - полным путём к элементу (CHAIN).
Последняя строка, если список отсортировать по этой строке - это последний элемент.
Один последний элемент в сортированным списке можно получить SELECT TOP 1 ... ORDER BY поле сортировки DESC

Согласен. Не точно выразился. Если взять больше данных и связей...в общем, вывести конечного ребёнка каждого родителя таким способом не получится)
Да почему же не получится???

Есть источник с несколькими родителями, джойните к нему этот CTE, используя outer apply, и те же top 1 и order by ... desc
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942472
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexeyvg
Есть источник с несколькими родителями, джойните к нему этот CTE, используя outer apply, и те же top 1 и order by ... desc
Например:
Код: 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.
declare @table1 TABLE (sess_id int, bl_sess_id int)  
	
INSERT INTO @table1
	([sess_id], [bl_sess_id])
VALUES
(78,394),(81,301),(100,379),(159,271),(195,288),
(202,334),(204,301),(215,389),(217,357),(269,301),
(271,502),(280,334),(301,271),(318,195),(323,301),(326,357),(334,204),(343,02),
(346,195),(349,542),(350,0),(357,301),
(365,404),(366,100),(372,404),(373,301),(374,301),(375,0),(379,334),(381,202),
(389,269),(394,357),(399,349),(403,349),
(404,560),(411,487),(426,373),(428,373),(432,487),(442,0),(453,301),
(457,204),(466,349),(470,366),(474,426),(481,301),(487,564),(491,349),(497,301),(502,271);

declare @roots TABLE (sess_id int) 
insert @roots values (78), (81)

;WITH T AS 
(
	SELECT 
		S0.sess_id AS Start, 
		S0.sess_id AS Parent, 
		S0.bl_sess_id AS Child, 
		CHAIN = CAST(CONCAT('-', S0.sess_id, '-', S0.bl_sess_id, '-') AS VARCHAR(1024))
	FROM @table1 S0
		JOIN @roots r on r.sess_id = S0.sess_id
	UNION ALL 
	SELECT 
		S1.Start, 
		S2.sess_id AS Parent, 
		S2.bl_sess_id AS Child, 
		CHAIN = CAST(CONCAT(S1.CHAIN, S2.bl_sess_id, '-') AS VARCHAR(1024)) 
	FROM T S1
		INNER JOIN @table1 S2 ON S1.Parent = S2.sess_id
	WHERE CHARINDEX(CONCAT('-', S2.bl_sess_id, '-'), S1.CHAIN) = 0
)

SELECT 	Start, 
		Parent, 
		Child, 
		CHAIN
FROM @roots r
	cross apply (
		SELECT TOP 1 
				Start, 
				Parent, 
				Child, 
				CHAIN
		FROM T t
		WHERE t.Start = r.sess_id
		ORDER BY CHAIN DESC
	) t

...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942708
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: 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.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
declare @table1 TABLE (sess_id int, bl_sess_id int)  
	
INSERT INTO @table1
	([sess_id], [bl_sess_id])
VALUES
(78,394),(81,301),(100,379),(159,271),(195,288),
(202,334),(204,301),(215,389),(217,357),(269,301),
(271,502),(280,334),(301,271),(318,195),(323,301),(326,357),(334,204),(343,02),
(346,195),(349,542),(350,0),(357,301),
(365,404),(366,100),(372,404),(373,301),(374,301),(375,0),(379,334),(381,202),
(389,269),(394,357),(399,349),(403,349),
(404,560),(411,487),(426,373),(428,373),(432,487),(442,0),(453,301),
(457,204),(466,349),(470,366),(474,426),(481,301),(487,564),(491,349),(497,301),
(502,271),(271,271),(502,601),(601,271),(1,2),(2,1),(1,15),(15,2),(2,3);

declare @roots TABLE (sess_id int) 
insert @roots values (78), (81), (1);

WITH N_TABLE AS

(SELECT X.sess_id, X.bl_sess_id,
        MAX(CASE X.gr WHEN 0 THEN X.rn END) AS sess_rn,
        MAX(CASE X.gr WHEN 1 THEN X.rn END) AS bl_sess_rn
 FROM (SELECT T.sess_id, T.bl_sess_id, S.gr, S.temp_id,
                DENSE_RANK() over(ORDER BY S.temp_id) AS rn
       FROM @table1 T
       CROSS APPLY(values (0, T.sess_id), (1, T.bl_sess_id)) S(gr, temp_id)
 ) X
 GROUP BY X.sess_id, X.bl_sess_id
)

,T AS 
(
	SELECT 
	        0 AS Chain_depth,
		S0.sess_id AS Start, 
		S0.sess_id AS Parent, 
		S0.bl_sess_id AS Child, 
		CHAIN = CAST(CONCAT('-', S0.sess_id, '-', S0.bl_sess_id, '-') AS VARCHAR(1024)),
                b.result as BIN_CHAIN
		
		
	FROM N_TABLE S0
		INNER JOIN @roots r ON r.sess_id = S0.sess_id
		
                CROSS APPLY dbo.fnSetBit(convert(BINARY(256), 0), S0.sess_rn) a
                CROSS APPLY dbo.fnSetBit(a.result, S0.bl_sess_rn) b		
		
		
	UNION ALL 
	
	SELECT 
	        a.Chain_depth + 1 AS Chain_depth,
	        a.start, 
	        a.Parent, 
	        a.Child, 
	        a.chain, 
	        i.result AS BIN_CHAIN
	        
	        
	FROM (SELECT 
	             S1.Chain_depth,
	             S1.Start, 
	             S2.sess_id AS Parent, 
		     S2.bl_sess_id AS Child, 
		     S2.bl_sess_rn AS Child_rn,
		     CHAIN = CAST(CONCAT(S1.CHAIN, S2.bl_sess_id, '-') AS VARCHAR(1024)),
		     s1.BIN_CHAIN
	      FROM T S1
		INNER JOIN N_TABLE S2 ON S1.Child = S2.sess_id
		
                CROSS APPLY dbo.fnMatchBit(s1.BIN_CHAIN, S2.bl_sess_rn) as BIN_MATCH

	      WHERE BIN_MATCH.result = 0
	      ) as a
	      
	CROSS APPLY dbo.fnSetBit(a.BIN_CHAIN, a.Child_rn) as i

)


SELECT 	Start, 
		Parent, 
		Child, 
		CHAIN,
		BIN_CHAIN
FROM @roots r
	CROSS APPLY (
		SELECT TOP 1 
				Start, 
				Parent, 
				Child, 
				CHAIN,
				BIN_CHAIN
		FROM T t
		WHERE t.Start = r.sess_id
		ORDER BY Chain_depth DESC
	) t

fiddle поиграться

Лимит на уникальные элементы 1024, больше - увеличивать binary.
Чем больше элементов в цепи , тем меньше будет занимать стоимость нумеровки в общем результате(эта хрень с dense_rank()).
Поменял TOP 1 на поиск наибольшей цепочки по количеству ID, поле CHAIN varchar(1024) исключительно для наглядности.
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942709
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexeyvg, кажется у Вас вот тут
Код: sql
1.
INNER JOIN @table1 S2 ON S1.Parent = S2.sess_id

надо Parent поменять на Child
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942712
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
nullin
alexeyvg, кажется у Вас вот тут
Код: sql
1.
INNER JOIN @table1 S2 ON S1.Parent = S2.sess_id


надо Parent поменять на Child
Может, и так, я не думая скопировал скрипт выше :-)
Но результат вроде получился правильный.

UPD Да, открыл скрипт, проверил, вы правы.
...
Рейтинг: 0 / 0
Найти последнего потомка.
    #39942717
nullin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если занудствовать, то у ТС граф, а не дерево
...
Рейтинг: 0 / 0
10 сообщений из 35, страница 2 из 2
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Найти последнего потомка.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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