MySQL 8.0 запрос для вычисления рекурсивного размера на каждом узле в иерархии на основе содержимого в нисходящем направлении - PullRequest
0 голосов
/ 06 апреля 2020

Это в MySQL 8.0.

Как использовать рекурсивный запрос для вычисления восходящего размера в каждом узле категории (тип = 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;

Начиная с данного узла в иерархии, в этом примере musi c, как мне достичь размера каждой группы категорий прямого потомка (type = 1) путем рекурсивного суммирования размеров файлов (type = 2) до Иерархия?

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
...

Изначально узлы типа = 1 имеют значение по умолчанию. Запрос рекурсивно вычисляет, какой размер основан на последующем содержимом.

Для вашего удобства место для скрипки: https://www.db-fiddle.com/f/wozz4B6TEVmU95RPrQxvYd/0

1 Ответ

0 голосов
/ 06 апреля 2020

Вы можете решить эту проблему с помощью пары рекурсивных CTE. Первая находит все категории на основе данного узла (в данном случае music), вторая находит все файлы, связанные с каждой из категорий, и строит таблицу их размеров со всеми категориями вплоть до категории root. , Затем эта таблица соединяется с таблицей категорий и размерами файлов, суммируемых на каждом уровне:

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

Демонстрация на dbfiddle

...