Выберите из таблицы, которая использует материализованный путь для кодирования дерева, упорядоченного по глубине (без рекурсивных/литров)

У меня есть таблица в реляционной базе данных, в которой я кодирую дерево, используя технику, известную как материализованный путь (также известный как Lineage колонка). То есть для каждого node в моем дереве у меня есть строка в таблице, и для каждой строки у меня есть строковый столбец с именем ancestry, где я храню путь от корня node до node, представленный этой строки.

Возможно ли, и если да - как, выберите строки в таблице orderd по предзаказу, то есть они должны появиться в результирующем наборе в порядке, который будет получен, посетив дерево depth-first. Я использую MySQL - так нет рекурсивных запросов и не имеет расширения ltree.

Например, дерево, его таблица и выбранные упорядочены по порядку:

 1        SELECT * FROM nodes   SELECT * FROM nodes ORDER BY ?depth_first_visit_order?
| \       id | ancestry         id | ancestry
2   3     -------------         -------------
|  | \    1  | NULL             1  | NULL           NOTE: I don't care about the
4  5  6   2  | 1                2  | 1                    order of siblings!
   |      3  | 1                4  | 1/2
   7      4  | 1/2              3  | 1
          5  | 1/3              5  | 1/3
          6  | 1/3              7  | 1/3/5
          7  | 1/3/5            6  | 1/3

Примечание. Мне явно интересно это сделать по материализованной кодировке пути!
Связанные: Каковы варианты хранения иерархических данных в реляционной базе данных?

+4
01 февр. '12 в 14:03
источник поделиться
2 ответа

Я считаю, что вы хотите алфавитную сортировку.

SELECT id, ancestry, ancestry + '/' + CAST(id as nvarchar(10)) AS PathEnumeration
FROM nodes
ORDER BY 3 ASC;

Я действительно не помню, как MySQL конкатенируется, но я уверен, что мой смысл ясен.

1
1/2
1/2/4
1/3
1/3/5
1/3/5/7
1/3/6

Обратите внимание, что это алфавитный вид, поэтому 11 будет отображаться до 2. Но вы сказали, что вас не волнует порядок братьев и сестер. Я, конечно, переписал бы его как вложенный набор;)

+1
14 февр. '12 в 4:55
источник

это будет заказывать последний номер вашей "родословной"

select *, 
Substring(ancestry,LEN(ancestry) - Charindex('/',Reverse(ancestry))+2, LEN(ancestry)) as END_CHAR
from nodes
order by END_CHAR desc

Я не пробовал с цифрами больше, чем 9, вам, возможно, придется наложить на int

0
01 февр. '12 в 16:03
источник

Посмотрите другие вопросы по меткам или Задайте вопрос