Я пытаюсь накапливать на каждом узле в иерархии количество прямых потомков. Для узлов, которые не имеют потомков, количество должно быть 0.
В общем, я хочу применять различные типы подсчета / агрегирования в нескольких контекстах, где иерархия точно не определена, как это. Поэтому меня интересует рекурсивное решение.
Рассмотрим следующий код. Как мне «инвертировать» этот запрос таким образом, чтобы вместо вычисления глубины я считал потомков и распространял числа вверх?
create table hierarchy (
name varchar(100),
location varchar(100),
parent_name varchar(100),
parent_location varchar(100)
) engine=InnoDB default charset=UTF8MB4;
truncate hierarchy;
insert into hierarchy values
('music', '/', NULL, NULL),
('classical', '/music', 'music', '/'),
('pop', '/music', 'music', '/'),
('rock', '/music', 'music', '/'),
('bach', '/music/classical', 'classical', '/music');
select * from hierarchy;
with recursive cte as
(
select name, location, parent_name, parent_location, 1 as depth
from hierarchy where parent_name is NULL and parent_location is NULL
union all
select a.name, a.location, a.parent_name, a.parent_location, depth + 1
from hierarchy as a inner join cte on a.parent_name = cte.name and a.parent_location = cte.location
)
select *
from cte;
Вывод
name location parent_name parent_location depth
'music' '/' NULL NULL 1
'classical' '/music' 'music' '/' 2
'pop' '/music' 'music' '/' 2
'rock' '/music' 'music' '/' 2
'bach' '/music/classical' 'classical' '/music' 3
Что меня в конечном итоге интересует в это вывод:
name location parent_name parent_location descendents
'music' '/' NULL NULL 3
'classical' '/music' 'music' '/' 1
'pop' '/music' 'music' '/' 0
'rock' '/music' 'music' '/' 0
'bach' '/music/classical' 'classical' '/music' 0