SQL - Выберите дочерние элементы в иерархии вместе с родительскими элементами - PullRequest
0 голосов
/ 27 сентября 2018

В моей базе данных есть отделы разных уровней, структурированные в иерархию:

  • Отдел 1 (уровень 0)
    • Отдел 2 (уровень 1)
      • Отдел 3 (уровень 2)
        • Отдел 4 (уровень 3)
      • Отдел 5 (уровень 2)
      • Отдел 6 (уровень 2)
    • Дивизион 7 (уровень 1)
  • Дивизион 8 (уровень 0)
    • Дивизион 9 (Уровень 1)
    • Отдел 10 (Уровень 1)
      • Отдел 11 (Уровень 2)

Используя рекурсию и CTE, я создаютаблица со всеми делениями в базе данных, упорядоченными по пути к ее иерархии (значение с плавающей запятой для удобства):

DivisionHierarchy

| DivisionID | DivisionName | ParentID | Level | SortOrder |
|          1 | Division 1   | NULL     | 0     | 1         |
|          2 | Division 2   | 1        | 1     | 1.1       |
|          3 | Division 3   | 2        | 2     | 1.11      |
|          4 | Division 4   | 3        | 3     | 1.111     |
|          5 | Division 5   | 2        | 2     | 1.12      |
|          6 | Division 6   | 2        | 2     | 1.13      |
|          7 | Division 7   | 1        | 1     | 1.2       |
|          8 | Division 8   | NULL     | 0     | 2         |
|          9 | Division 9   | 8        | 1     | 2.1       |
|         10 | Division 10  | 8        | 1     | 2.2       |
|         11 | Division 11  | 10       | 2     | 2.21      |

Затем у меня есть еще одна таблица с выбранными делениями:

SelectedDivisions

| DivisionID |
|          3 |
|         10 |

Учитывая выбранные подразделения, мне нужно отфильтровать таблицу DivisionHierarchy, чтобы показать:

  • выбранные подразделения;
  • все дочерние подразделения для выбранного Diвидения (включая вложенные дочерние элементы);
  • Подразделения, которые являются родительскими для выбранных, но только те, которые ссылаются на них в своем структурном пути.

Итак, для DivisionID IN (3, 10), выходные данные должны быть:

  • Отдел 1 (уровень 0)
    • Отдел 2 (уровень 1)
      • Отдел 3 (уровень 2)
        • Отдел 4 (уровень 3)
  • Отдел 8 (Уровень 0)
    • Отдел 10 (Уровень1)
      • Отдел 11 (Уровень 2).

Выход:

| DivisionID | DivisionName | ParentID | Level | SortOrder |
|          1 | Division 1   | NULL     | 0     | 1         |
|          2 | Division 2   | 1        | 1     | 1.1       |
|          3 | Division 3   | 2        | 2     | 1.11      |
|          4 | Division 4   | 3        | 3     | 1.111     |
|          8 | Division 8   | NULL     | 0     | 2         |
|         10 | Division 10  | 8        | 1     | 2.2       |
|         11 | Division 11  | 10       | 2     | 2.21      |

Не могли бы вы, пожалуйстаподскажите как мне этого добиться?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Я достиг желаемого результата, переписав последнюю часть как:

;WITH CTE_Parents
AS
(
    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN @SelectedDivisions s
            ON h.DivisionID = s.DivisionID

    UNION ALL

    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN CTE_Parents c ON c.DivisionID = h.ParentID
),
CTE_Children
AS
(
    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN @SelectedDivisions s
            ON h.DivisionID = s.DivisionID

    UNION ALL

    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN CTE_Children c ON c.ParentID = h.DivisionID
)

SELECT * FROM CTE_Parents
UNION
SELECT * FROM CTE_Children
ORDER BY SortOrder
0 голосов
/ 27 сентября 2018

Я попытался выполнить это с помощью приведенного ниже сценария, однако это два результата запроса, которые должны быть объединены (и я не знаю, как).Но, возможно, это направит вас в правильном направлении.

DECLARE @DivisionHierarchy TABLE
(
    DivisionID TINYINT NOT NULL,
    DivisionName VARCHAR(20) NOT NULL,
    ParentID TINYINT,
    [Level] TINYINT NOT NULL,
    SortOrder VARCHAR(20) NOT NULL
)
INSERT INTO @DivisionHierarchy VALUES (1, 'Division 1', NULL, 0, '1');
INSERT INTO @DivisionHierarchy VALUES (2, 'Division 2', 1, 1, '1.1');
INSERT INTO @DivisionHierarchy VALUES (3, 'Division 3', 2, 2, '1.11');
INSERT INTO @DivisionHierarchy VALUES (4, 'Division 4', 3, 3, '1.111');
INSERT INTO @DivisionHierarchy VALUES (5, 'Division 5', 2, 2, '1.12');
INSERT INTO @DivisionHierarchy VALUES (6, 'Division 6', 2, 2, '1.13');
INSERT INTO @DivisionHierarchy VALUES (7, 'Division 7', 1, 1, '1.2');
INSERT INTO @DivisionHierarchy VALUES (8, 'Division 8', NULL, 0, '2');
INSERT INTO @DivisionHierarchy VALUES (9, 'Division 9', 8, 1, '2.1');
INSERT INTO @DivisionHierarchy VALUES (10, 'Division 10', 8, 1, '2.2');
INSERT INTO @DivisionHierarchy VALUES (11, 'Division 11', 10, 2, '2.21');

SELECT * FROM @DivisionHierarchy ORDER BY DivisionID;

DECLARE @SelectedDivisions TABLE
(
    DivisionID TINYINT
);
INSERT INTO @SelectedDivisions VALUES (3);
INSERT INTO @SelectedDivisions VALUES (10);


;WITH CTE
AS
(
    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN @SelectedDivisions s
            ON h.DivisionID = s.DivisionID

    UNION ALL

    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN CTE c ON c.DivisionID = h.ParentID
)
SELECT * FROM CTE ORDER BY DivisionID

;WITH CTE
AS
(
    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN @SelectedDivisions s
            ON h.DivisionID = s.DivisionID

    UNION ALL

    SELECT h.*
    FROM @DivisionHierarchy h
        INNER JOIN CTE c ON c.ParentID = h.DivisionID
)
SELECT * FROM CTE ORDER BY DivisionID
...