2015-03-11 2 views
2

У меня есть данные в следующем формате в Names таблицы в базе данных:запрос, чтобы получить родительские записи с ребенком записи, а затем последующие родитель-потомок записей в MySQL

ID | Name      | ParentID 
1 | Parent 1     | 0 
2 | Parent 2     | 0 
3 | Parent 1 Child 1   | 1 
4 | Parent 2 Child 1   | 2 
5 | Parent 1 Child 1 Child | 3 
6 | Parent 2 Child 1 Child 1 | 4 
7 | Parent 2 Child 1 Child 2 | 4 

Столбец ParentID оказывает данные ID в качестве родительской записи. ParentID с 0 Значение указывает корневые элементы. Мне нужно написать запрос, чтобы получить данные в следующем порядке:

ID | Name      | ParentID 
1 | Parent 1     | 0 
3 | Parent 1 Child 1   | 1 
5 | Parent 1 Child 1 Child | 3 
2 | Parent 2     | 0 
4 | Parent 2 Child 1   | 2  
6 | Parent 2 Child 1 Child 1 | 4 
7 | Parent 2 Child 1 Child 2 | 4 

мне нужно получить корневой записи (запись с ParentID как 0), а затем все child и sub-children этого корня записи, а затем получить следующая корневая запись, а затем child и sub-children этой корневой записи и так далее.

ответ

7

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

+----+--------------------------+----------+------------------+ 
| ID |   Name   | ParentID | MaterializedPath | 
+----+--------------------------+----------+------------------+ 
| 1 | Parent 1     |  0 | 1    | 
| 2 | Parent 2     |  0 | 2    | 
| 4 | Parent 2 Child 1   |  2 | 2.4    | 
| 6 | Parent 2 Child 1 Child 1 |  4 | 2.4.6   | 
| 7 | Parent 2 Child 1 Child 2 |  4 | 2.4.7   | 
| 3 | Parent 1 Child 1   |  1 | 1.3    | 
| 5 | Parent 1 Child 1 Child |  3 | 1.3.5   | 
+----+--------------------------+----------+------------------+ 

Каждый узел N имеет материализованного путь, этот путь указывает вам путь от корневого узла к узлу N. Это может быть конкатенирование идентификатора узла. Например, чтобы достичь узла 5, начиная с корневого узла, вы посетите узел 1, узел 3 и узел 5, поэтому узел 5 материализовались путь 1.3.5

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

В предыдущем примере материализованные пути представляют собой строки объединения строк, но я предпочитаю двоичную конкатенацию по ряду причин.

Чтобы построить материализованные пути вам понадобится следующее рекурсивное ОТВ:

CREATE TABLE Tree 
(
    ID int NOT NULL CONSTRAINT PK_Tree PRIMARY KEY, 
    Name nvarchar(250) NOT NULL, 
    ParentID int NOT NULL, 
) 

INSERT INTO Tree(ID, Name, ParentID) VALUES 
(1, 'Parent 1', 0), 
(2, 'Parent 2', 0), 
(3, 'Parent 1 Child 1', 1), 
(4, 'Parent 2 Child 1', 2), 
(5, 'Parent 1 Child 1 Child', 3), 
(6, 'Parent 2 Child 1 Child 1', 4), 
(7, 'Parent 2 Child 1 Child 2', 4) 

GO 
WITH T AS 
(
    SELECT 
     N.ID, N.Name, N.ParentID, CAST(N.ID AS varbinary(512)) AS MaterializedPath 
    FROM 
     Tree N 
    WHERE 
     N.ParentID = 0 

    UNION ALL 

    SELECT 
     N.ID, N.Name, N.ParentID, CAST(T.MaterializedPath + CAST(N.ID AS binary(4)) AS varbinary(512)) AS MaterializedPath 
    FROM 
     Tree N INNER JOIN T 
      ON N.ParentID = T.ID 

) 
SELECT * 
FROM T 
ORDER BY T.MaterializedPath 

Результат:

+----+--------------------------+----------+----------------------------+ 
| ID |   Name   | ParentID |  MaterializedPath  | 
+----+--------------------------+----------+----------------------------+ 
| 1 | Parent 1     |  0 | 0x00000001     | 
| 3 | Parent 1 Child 1   |  1 | 0x0000000100000003   | 
| 5 | Parent 1 Child 1 Child |  3 | 0x000000010000000300000005 | 
| 2 | Parent 2     |  0 | 0x00000002     | 
| 4 | Parent 2 Child 1   |  2 | 0x0000000200000004   | 
| 6 | Parent 2 Child 1 Child 1 |  4 | 0x000000020000000400000006 | 
| 7 | Parent 2 Child 1 Child 2 |  4 | 0x000000020000000400000007 | 
+----+--------------------------+----------+----------------------------+ 

выше рекурсивной КТР начинается с корневых узлов. Вычисление материализованного пути для корневого узла тривиально просто, это идентификатор самого узла. На следующей итерации CTE соединяет корневые узлы с дочерними узлами. Материализованный путь для дочернего узла CN является конкатенацией материализованного пути его родительского узла PN и идентификатора узла CN. Последующие итерации продвигаются на один уровень вниз по дереву до тех пор, пока не будут достигнуты узлы листа.

Смежные вопросы