MySQL 8.0 查询根据下游内容递归计算层次结构中每个节点的大小
MySQL 8.0 query to compute recursively size at each node in the hierarchy based on the contents downstream
这是在 MySQL 8.0.
如何使用递归查询自下而上计算每个类别节点(type = 1)的大小。
create table hierarchy (
name varchar(100),
location varchar(100),
type int,
size int,
parent_name varchar(100),
parent_location varchar(100)
) engine=InnoDB default charset=UTF8MB4;
truncate hierarchy;
insert into hierarchy values
('music', '/', 1, 0, NULL, NULL),
('classical', '/music', 1, 0, 'music', '/'),
('pop', '/music', 1, 0, 'music', '/'),
('bonjovi', /music/pop', 'pop', '/music'),
('its_my_life.mp3', '/music/pop/bonjovi', 2, 4092, 'bonjovi', '/music/pop'),
('bach', '/music/classical', 1, 'classical', '/music'),
('flute_e_min.mp3', '/music/classical/bach', 2, 1024, 'bach', '/music/classical'),
('sonata_no1_g.mp3, '/music/classical/bach', 2, 2048, 'bach', '/music/classical'),
select * from hierarchy;
从层次结构中的给定节点开始,在这个示例音乐中,我如何通过递归地总结(type = 2)的文件大小来获得每个直接后代类别组(type = 1)的大小向上层级?
name location parent_name parent_location total size
'music' '/' NULL NULL 7164
'classical' '/music' 'music' '/' 3072
'pop' '/music' 'music' '/' 4092
'bonjovi' '/music/pop' 'pop' '/music' 4092
'bach' '/music/classical' 'classical' '/music' 3072
...
最初,type = 1 的节点有一个默认值。查询递归地计算基于下游内容的大小。
为了您的方便 fiddle space: https://www.db-fiddle.com/f/wozz4B6TEVmU95RPrQxvYd/0
你可以用一对递归 CTE 来解决这个问题。第一个根据给定节点查找所有类别(在本例中为 music
),第二个查找与每个类别关联的所有文件,并构建一个 table 大小的 table 以及所有类别到根类别。然后将此 table 加入类别的 table 中,每个级别的文件大小总和:
WITH RECURSIVE categories AS (
SELECT name, location, parent_name, parent_location, size
FROM hierarchy
WHERE name = 'music'
UNION ALL
SELECT h.name, h.location, h.parent_name, h.parent_location, h.size
FROM hierarchy h
JOIN categories c ON c.name = h.parent_name
WHERE h.type = 1
),
filesizes AS (
SELECT size, parent_name
FROM hierarchy
WHERE type = 2 AND parent_name IN (SELECT name FROM categories)
UNION ALL
SELECT f.size, h.parent_name
FROM hierarchy h
JOIN filesizes f ON f.parent_name = h.name
WHERE h.parent_name IS NOT NULL
)
SELECT c.name, c.location, c.parent_name, c.parent_location,
SUM(f.size) AS total_size
FROM categories c
JOIN filesizes f ON f.parent_name = c.name
GROUP BY c.name, c.location, c.parent_name, c.parent_location
输出:
name location parent_name parent_location total_size
music / null null 7164
classical /music music / 3072
pop /music music / 4092
bonjovi /music/pop pop /music 4092
bach /music/classical classical /music 3072
这是在 MySQL 8.0.
如何使用递归查询自下而上计算每个类别节点(type = 1)的大小。
create table hierarchy (
name varchar(100),
location varchar(100),
type int,
size int,
parent_name varchar(100),
parent_location varchar(100)
) engine=InnoDB default charset=UTF8MB4;
truncate hierarchy;
insert into hierarchy values
('music', '/', 1, 0, NULL, NULL),
('classical', '/music', 1, 0, 'music', '/'),
('pop', '/music', 1, 0, 'music', '/'),
('bonjovi', /music/pop', 'pop', '/music'),
('its_my_life.mp3', '/music/pop/bonjovi', 2, 4092, 'bonjovi', '/music/pop'),
('bach', '/music/classical', 1, 'classical', '/music'),
('flute_e_min.mp3', '/music/classical/bach', 2, 1024, 'bach', '/music/classical'),
('sonata_no1_g.mp3, '/music/classical/bach', 2, 2048, 'bach', '/music/classical'),
select * from hierarchy;
从层次结构中的给定节点开始,在这个示例音乐中,我如何通过递归地总结(type = 2)的文件大小来获得每个直接后代类别组(type = 1)的大小向上层级?
name location parent_name parent_location total size
'music' '/' NULL NULL 7164
'classical' '/music' 'music' '/' 3072
'pop' '/music' 'music' '/' 4092
'bonjovi' '/music/pop' 'pop' '/music' 4092
'bach' '/music/classical' 'classical' '/music' 3072
...
最初,type = 1 的节点有一个默认值。查询递归地计算基于下游内容的大小。
为了您的方便 fiddle space: https://www.db-fiddle.com/f/wozz4B6TEVmU95RPrQxvYd/0
你可以用一对递归 CTE 来解决这个问题。第一个根据给定节点查找所有类别(在本例中为 music
),第二个查找与每个类别关联的所有文件,并构建一个 table 大小的 table 以及所有类别到根类别。然后将此 table 加入类别的 table 中,每个级别的文件大小总和:
WITH RECURSIVE categories AS (
SELECT name, location, parent_name, parent_location, size
FROM hierarchy
WHERE name = 'music'
UNION ALL
SELECT h.name, h.location, h.parent_name, h.parent_location, h.size
FROM hierarchy h
JOIN categories c ON c.name = h.parent_name
WHERE h.type = 1
),
filesizes AS (
SELECT size, parent_name
FROM hierarchy
WHERE type = 2 AND parent_name IN (SELECT name FROM categories)
UNION ALL
SELECT f.size, h.parent_name
FROM hierarchy h
JOIN filesizes f ON f.parent_name = h.name
WHERE h.parent_name IS NOT NULL
)
SELECT c.name, c.location, c.parent_name, c.parent_location,
SUM(f.size) AS total_size
FROM categories c
JOIN filesizes f ON f.parent_name = c.name
GROUP BY c.name, c.location, c.parent_name, c.parent_location
输出:
name location parent_name parent_location total_size
music / null null 7164
classical /music music / 3072
pop /music music / 4092
bonjovi /music/pop pop /music 4092
bach /music/classical classical /music 3072