Найти уровень категорий в иерархии - PullRequest
0 голосов
/ 29 мая 2020

У меня есть скрипт для поиска иерархии списка категорий. Однако мне нужно знать глубину уровня, чтобы найти все соответствующие категории. Итак, мой вопрос: есть ли лучший способ переписать код, чтобы он мог развернуться до самого низкого уровня без необходимости указывать, насколько глубоко до go. В приведенном ниже примере я должен был знать, что уровень категории достигает 5 уровня, чтобы найти все категории.

WITH rCTE AS
(
    SELECT
        *,
        0 AS Level
    FROM dbo.inv_category ic
    WHERE ic.Primary_org_id = 56392

    UNION ALL

    SELECT
        t.*,
        r.Level + 1 AS Level
    FROM dbo.inv_category t
    INNER JOIN rCTE r ON t.Parent_id = r.Category_id
)
SELECT DISTINCT
    c1.Parent_id, c1.Category_id, c1.Category,
    c2.Category, c2.Category_id, c2.Parent_id,
    c3.Category, c3.Category_id, c3.Parent_id,
    c4.Category, c4.Category_id, c4.Parent_id,
    c5.Category, c5.Category_id, c5.Parent_id
FROM 
    rCTE c1
LEFT OUTER JOIN 
    rCTE c2 ON c1.Category_id = c2.Parent_id
LEFT OUTER JOIN 
    rCTE c3 ON c2.Category_id = c3.Parent_id
LEFT OUTER JOIN 
    rCTE c4 ON c3.Category_id = c4.Parent_id
LEFT OUTER JOIN 
    rCTE c5 ON c4.Category_id = c5.Parent_id
WHERE 
    c1.Parent_id = 0
ORDER BY 
    c1.Category, c2.Category

1 Ответ

1 голос
/ 29 мая 2020

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

Один из вариантов сокращения запроса и предотвращения множественных объединений использует условную агрегацию:

with rcte as (...)
select
    max(case when level = 0 then parent_id   end) parent_id_0,
    max(case when level = 0 then category_id end) category_id_0,
    max(case when level = 0 then category    end) category_0,
    max(case when level = 1 then parent_id   end) parent_id_1,
    max(case when level = 1 then category_id end) category_id_1,
    max(case when level = 1 then category    end) category_1,   
    ...
from rcte

Вы можете добавить больше троек условных выражений, чтобы управлять максимальным количеством уровней по мере необходимости; когда фактическая иерархия продукта исчерпывается, следующие столбцы останутся пустыми.

Другой вариант - агрегирование строк. Это создает уникальный столбец для каждого исходного столбца, в котором все значения объединяются в порядке, в котором они появляются в иерархии:

with rcte as (...)
select
    string_agg(parent_id,      ' > ') within group(order by level) parent_ids,
    string_agg(category_id_id, ' > ') within group(order by level) category_ids,
    string_agg(category,       ' > ') within group(order by level) categories
from rcte
...