Как я могу получить данные об иерархической структуре? - PullRequest
0 голосов
/ 25 февраля 2020

В моей базе данных PostgreSQL есть таблица с именем answers. В этой таблице хранится информация о том, как пользователи отвечают на определенные вопросы. Также у меня есть таблица organizations, в которой хранится информация об иерархических отношениях между организациями.

PostgreSQL версия: PostgreSQL 11.4 (в Debian)

Таблица answers имеет такие структура:

| employee | tree_organization_id | question_id | question_text                 | option_id | option_text |
|----------|----------------------|-------------|-------------------------------|-----------|-------------|
| Alex     | \1                   | 1           | What is your favourite color? | 1         | Red         |
| Mark     | \1\2\3               | 1           | What is your favourite color? | 3         | Brown       |
| Lily     | \1\2\4               | 1           | What is your favourite color? | 2         | Yellow      |
| Grace    | \1\2\4               | 1           | What is your favourite color? | 1         | Red         |
| Evie     | \5                   | 1           | What is your favourite color? | 1         | Red         |
| Bob      | \5\6                 | 1           | What is your favourite color? | 2         | Yellow      |
| Mark     | \5\7                 | 1           | What is your favourite color? | 3         | Brown       |

Таблица organizations имеет такое значение:

| organization_id | organization_name | parent_organization_id | tree_organization_id | organization_rang |
|-----------------|-------------------|------------------------|----------------------|-------------------|
| 1               | Alphabet          |                        | \1                   | 1                 |
| 2               | Google            | 1                      | \1\2                 | 2                 |
| 3               | Calico            | 1                      | \1\3                 | 2                 |
| 4               | Youtube           | 2                      | \1\2\4               | 3                 |
| 5               | Nest              | 2                      | \1\2\5               | 3                 |
| 6               | Facebook          |                        | \6                   | 1                 |
| 7               | Whatsapp          | 5                      | \6\7                 | 2                 |
| 8               | Instagram         | 5                      | \6\8                 | 2                 |

Допустим, в качестве входных данных у меня указано значение c organization_id. Например, это может быть 4 (Youtube). Мне нужно показать количество людей, которые ответили на вопрос в этой организации и ее родителях.

Другими словами, я пытаюсь получить аналогичный результат:

| organization_id | organization_name | tree_organization_id | total           |
|-----------------|-------------------|----------------------|-----------------|
| 1               | Alphabet          | \1                   | 3               | <- Alex, Lily, Grace
| 2               | Google            | \1\2                 | 2               | <- Lily, Grace
| 4               | Youtube           | \1\2\4               | 2               | <- Lily, Grace

Я пытался такой код, но он неправильно рассчитывает родительские организации.

select
    organizations.organization_id,
    organizations.organization_name,
    organizations.tree_organization_id,
    calculation.total
from
    organizations
join lateral (
    select
        count(*) as total
    from
        answers
    where
        tree_organization_id like concat('%', '\', organizations.organization_id, '%')
    and
        question_id = 1
) calculation on 1 = 1
where
    organization_id in (4);

Кроме того, я использовал такой код. Я нашел родителей организации, но как правильно рассчитать значения в столбце total?

with recursive organizations_hierarchy as (
    select
        organizations.organization_id,
        organizations.organization_name,
        organizations.parent_organization_id,
        organizations.tree_organization_id,
        organizations.organization_rang
    from
        organizations
    where
        organizations.organization_id in (4)
    union all
    select
        a.organization_id,
        a.organization_name,
        a.parent_organization_id,
        a.tree_organization_id,
        a.organization_rang
    from
        organizations a
    inner join
        organizations_hierarchy b
    on
        a.organization_id = b.parent_organization_id
)
select
    organizations_hierarchy.organization_id,
    organizations_hierarchy.organization_name,
    organizations_hierarchy.tree_organization_id
from
    organizations_hierarchy
order by
    organizations_hierarchy.organization_rang;

1 Ответ

0 голосов
/ 28 февраля 2020

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

select
    x.organization_id,
    x.organization_name,
    x.tree_organization_id,
    calculation.total
from (
    with recursive organizations_hierarchy as (
        select
            organizations.organization_id,
            organizations.organization_name,
            organizations.organization_rang,
            organizations.parent_organization_id,
            organizations.tree_organization_id
        from
            organizations
        where
            organizations.orgnization_id in(4)
        union
        select
            a.organization_id,
            a.organization_name,
            a.organization_rang,
            a.parent_organization_id,
            a.tree_organization_id
        from
            organizations a
        inner join
            organizations_hierarchy b
        on
            a.organization_id = b.parent_organization_id
    )
    select
        a.*,
        (
            select
                array_agg(b.tree_organization_id order by b.organization_rang)
            from
                organizations_hierarchy b
            where
                B.tree_organization_id like CONCAT('%', '\', a.organization_id, '%')
        ) as hierarchy
    from
        organizations_hierarchy a
    order by
        a.organization_rang,
        a.organization_id
) x
join lateral (
    select
        count(*) as total
    from
        answers
    where
        tree_organization_id = any(x.hierarchy)
    and
        question_id = 1
) calculation on 1 = 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...