CTE - обратная иерархия - PullRequest
       4

CTE - обратная иерархия

0 голосов
/ 04 января 2011

Мне нужно создать хлебную крошку, как путь групп определенного контакта .

T_GROUP хранит фактическую иерархию групп:

GROUP_ID    NAME            PARENT_ID   LEVEL
    7      g1              NULL         1
    80    Workgroups      7            2
    82    Advocacy        80           3

В таблице T_CONTACT_GROUP хранятся группы, принадлежащие контактам:

CONTACT_ID  GROUP_ID 
55          82
56            7
55            7

Теперь я хотел бы получить набор результатов следующим образом для идентификатора контакта 55 : Обратите внимание, что в ожидаемом наборе результатов g1 дважды пришел, поскольку контакту 55 также была назначена группа 7.

contactId GROUP_ID NAME PARENT_ID   LEVEL
55        7     g1      NULL        1
55        80       g1|Workgroups 7 2
55       82        g1|Workgroups|Advocacy 80 3
55       7         g1 NULL 1

1 Ответ

2 голосов
/ 04 января 2011

Есть как минимум два способа сделать это.Вы упоминаете CTE в своем названии, так что я пойду с этим первым.По ссылке здесь У меня есть пример иерархического CTE, небольшого массажа, и он будет представлять родителей, а не детей:

WITH Hierarchy (Group_ID, Name, Parent_ID, Level) AS
(
    SELECT Group_ID, Name, Parent_ID, Level
    FROM T_Group
    WHERE Contact_id = @Leaf
UNION ALL 
    SELECT g.Group_ID, g.Name, g.Parent_ID, g.Level
    FROM T_Group g
    INNER JOIN Hierarchy h ON g.Group_ID = h.Parent
)

Этот CTE будет помещен в хранимую процедуруили таблица User Defined Function, принимающая параметр @Leaf (конечный узел, для которого вы ищете. В вашем примере это 82, а затем 7).

Проблема в том, что иерархические CTE могут быть очень дорогими,особенно если вы работаете с более глубокими древовидными структурами или вызываетесь повторно.Кэширование может помочь, но есть и другие варианты.

Другой способ - сохранить иерархию родителей в объединенном со строкой поле рядом с вашими группами:

GROUP_ID NAME      PARENT_ID LEVEL PARENTS
82        Advocacy 80        3     |7|80|82|

Затем можно сделать что-то вроде:

SELECT p.Group_ID, g.Name, g.Parent_ID, g.Level
FROM T_GROUP g
CROSS JOIN dbo.StringSplit('|', Parents) p
WHERE p.Value = g.Group_ID

, чтобы получить все данные родителей.Это имеет тенденцию быть намного более эффективным, чем использование CTE для обработки поиска.Это означает, что когда вы вставляете новые записи в GROUP, вы также должны создавать родительское поле.Обычно, чтобы справиться с этим, вы должны создать хранимую процедуру, которая создала для вас группу, при необходимости создав родительскую группу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...