Подсчет сверху вниз в иерархических sql данных - PullRequest
0 голосов
/ 26 мая 2020

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

таблицы настроены следующим образом:

тип

ID    Text        Number
1     Tree        20
2     Flowers     10
3     Electro     20
4     Rose        10
5     Violet      5
6     Red Rose    12
7     Television  100
8     Radio       70

отношение

ID    src_id      dst_id   depth
1     1           2        1
2     2           3        2
3     3           4        3
4     5           6        1
5     5           7        1
6     7           8        2

Иерархия будет выглядеть так:

ID    Text        Number
1     Tree        20
|2    Flowers     10
|-3   Rose        10
| |-4 Red Rose    12
5     Violet      5
|6    Electro     20
|7    Television  100
|-8   Radio       70

И вот как должен выглядеть мой результат, самое главное - количество чисел для каждого поддерева, как это:

ID    Text        AggregateCount   Level  Path
1     Tree        52               0      Tree
2     Flowers     32               1      Tree / Flowers
3     Rose        22               2      Tree / Flowers / Rose
4     Red Rose    12               3      Tree / Flowers / Rose / Red Rose
5     Violet      195              0      Violet
6     Electro     20               1      Violet / Electro
7     Television  170 (70+100)     1      Violet / Television
8     Radio       70               2      Violet / Television / Radio

Я всегда старался начинать с уровней листьев и работать путь вверх с CTE. Но я просто не могу подсчитать и выбрать правильный путь. Будем очень признательны за некоторые рекомендации.

Вот одна из многих неудачных попыток:

WITH Hierarchy AS (

    SELECT 
        type.[id],
        type.text,
        ISNULL((SELECT depth from relation WHERE relation.dst_id = type.id), 0) AS levelC,
        type.number as aggregatedNumber,    
        CAST(type.text as VARCHAR(255)) AS PathC
    FROM type
    -- only select children
    WHERE type.[id] NOT IN (
        SELECT src_id from know_area_relation
    )
    UNION ALL
        SELECT 
            type_source.id,
            Hierarchy.text,
            levelC - 1,
            Hierarchy.aggregatedNumber + type_dest.number,
            CAST(type_source.text + ' / '+ PathC   as VARCHAR(255)) AS PathC
    FROM relation   
    INNER JOIN type type_source
        ON type_source.id = relation.src_id
    INNER JOIN type type_dest
        ON type_dest.id = relation.dst_id
    INNER JOIN Hierarchy
        ON Hierarchy.id = relation.dst_id 
)
SELECT * from Hierarchy
Order by LevelC DESC

и вот DDL:

CREATE TABLE type
(
    id int IDENTITY(1,1) PRIMARY KEY,
    text varchar(50),
    number INT
)


CREATE TABLE relation (
    id int IDENTITY(1,1) PRIMARY KEY,
    src_id      int NOT NULL,
    dst_id      int NOT NULL,
    depth       int NOT NULL,
    CONSTRAINT fk_source FOREIGN KEY (src_id)
    REFERENCES type(id),
    CONSTRAINT fk_dest FOREIGN KEY (dst_id)
    REFERENCES type(id)
);
...