рекурсивное представление с использованием справочных таблиц с неоднозначными объединениями - PullRequest
0 голосов
/ 05 июня 2018

Я даже не знаю, как озаглавить этот вопрос, но я надеюсь, что это имеет смысл.

У меня есть три таблицы:

  1. Таблица пользователей и их данные
  2. Таблица групп и ее подробности
  3. Таблица групп с идентификатором поиска ее членов, которые взяты из таблицы пользователей или групп

3-я таблица имеетдва столбца:

  1. Идентификатор группы, который соответствует строке в таблице групп (2-й)
  2. Идентификатор участника, который соответствует строке в либо пользователей (1-й) или группы (2-й) таблицы

Примечания:

  • Идентификаторы таблицы пользователей и групп уникальны друг для друга.Например, если у пользователя ID = 1, то ни у другого пользователя, ни у какой-либо группы не будет такого идентификатора.
  • Группа может иметь в качестве участника пользователя или другую группу.

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

1.пользователи

| ID | user_name |
|----|-----------|
|  1 | one       |
|  2 | two       |
|  3 | three     |
|  4 | four      |
|  5 | five      |

2.группы

| ID | group_name |
|----|------------|
|  6 | six        |
|  7 | seven      |
|  8 | eight      |
|  9 | nine       |
| 10 | ten        |

3.члены группы

| group_ID | member_ID |
|----------|-----------|
|        6 |         1 |
|        6 |         2 |
|        6 |         3 |
|        7 |         4 |
|        7 |         5 |
|        8 |         1 |
|        8 |         9 |
|        8 |        10 |
|        9 |         5 |
|       10 |         1 |
|       10 |         8 |

4.вывод / результат

| group_ID | user_ID | user_name   | group_path
|----------|---------|-------------|------------
|        6 |       1 | one         | six
|        6 |       2 | two         | six
|        6 |       3 | three       | six
|        7 |       4 | four        | seven
|        7 |       5 | five        | seven
|        8 |       1 | one         | eight
|        8 |       5 | five        | eight > nine
|        8 |       1 | one         | eight > ten
|        8 |         | [recursive] | eight > ten > eight
|        9 |       5 | five        | nine
|       10 |       1 | one         | ten
|       10 |       1 | one         | ten > eight
|       10 |       5 | five        | ten > eight > nine
|       10 |         | [recursive] | ten > eight > ten

1 Ответ

0 голосов
/ 05 июня 2018

Вот ответ и живое демо

;with cte as 
(
select id,name=user_name, type='U' from users
union
select  id, name=group_name, type='G' from groups
)
, cte2 as 
(
    select 
        user_id=c.id, 
        user_name=c.name,
        group_Id=g.group_ID,
        group_path= cast(c2.name as nvarchar(max))
    from cte c 
    left join [group members] g 
        on g.member_id=c.id and type='U'
    left join cte c2  
        on c2.type='G' and c2.id=g.group_ID
    union all
    select 
        user_id=user_id, 
        user_name=user_name,
        group_Id=g.group_ID,
        group_path= concat(c2.name,'>',c.group_path)
    from cte2 c
        join [group members] g 
        on g.member_id=c.group_Id
       join cte c2
       on g.group_ID=c2.id and c2.type='G'
        where c.group_path not like '%'+c2.name+'%'  
 )
 select 
     group_id,
     user_id,
     user_name, 
     group_path 
 from cte2
 where group_id is not null
 union all
 select 
     group_id=g.group_ID,
     user_id= NULL,
     user_name='[recursive]',
     group_path=concat(c2.name,'>',c.group_path)
 from cte2 c 
 join [group members] g
     on g.member_id=c.group_Id
     join cte c2
       on g.group_ID=c2.id and c2.type='G'
        where c.group_path like '%'+c2.name+'%'
  order by group_id,user_id
...