2012-04-27 5 views
2

Я использую модель списка смежности для хранения (очень динамической) древовидной структуры в базе данных MySQL. Мне нужен способ выбрать всех потомков данного узла, желательно с помощью одного вызова хранимой процедуры. Я знаю, что модель вложенных наборов сделает это легко, но это сделает другие вещи очень трудными, так что, к сожалению, это не вариант для меня. Вот что у меня до сих пор:Выбор всех потомков узла дерева

DELIMITER // 

CREATE PROCEDURE get_descendants(node_id INT) 
    BEGIN 

    DROP TEMPORARY TABLE IF EXISTS descendants; 
    CREATE TEMPORARY TABLE descendants (id INT, name VARCHAR(100), parent_id INT); 

    INSERT INTO descendants 
     SELECT * 
     FROM nodes 
     WHERE parent_id <=> node_id; 

    -- ...? 

    END// 

DELIMITER ; 

Идея заключается в том, чтобы сверлить вниз и добавления детей в таблицу потомков, пока не достигнет листьев. Затем я могу получить доступ к временной таблице вне процедуры ... Надеюсь. (Это действительно отстой, что я не могу вернуть результирующий набор из сохраненной функции.)

Мне нужно как-то перебрать результаты и выдать новый оператор SELECT для каждой строки. Я читал, что курсоры могут помочь здесь, но я не понимаю, как это сделать. Кажется, что с помощью курсоров вам нужно выбрать все впереди, а затем повторить.

+0

Вложенные наборы - это не единственный вариант. Столы для закрытия также заслуживают внимания. – eggyal

+0

На самом деле, я только что открыл закрытые столы сегодня днем! Они кажутся многообещающими, но они не очень хорошо обрабатывают операции перемещения. http://www.mysqlperformanceblog.com/2011/02/14/moving-subtrees-in-closure-table/ В этом смысле они вроде как вложенные наборы. Я буду учиться. – Metaphile

+0

Выбор подходящей структуры данных для ваших нужд - это понимание того, как часто вам нужно выполнять различные типы операций - так как каждое решение разворачивает время против пространства по-разному. Если ваш график довольно статичен, и вам часто нужно проверять пути через него, то список смежности, вероятно, не самый лучший выбор; однако это может быть идеальным решением, если график очень динамичен, и вам редко приходится проверять больше, чем непосредственно соседние соседи любого данного узла. – eggyal

ответ

0

Это до read : write соотношение. Если у вас очень высокий уровень чтения, очень полезно составить таблицу взаимозависимости, а не временную.

Псевдо подход (не реальный код!):

1. node(1) has child node(2) 
    -> Insert a row with (parent_id = 1, child_id = 2, direct = True) 

2. node(2) has child node(3) 
    -> Insert a row with (parent_id = 2, child_id = 3, direct = True) 
    -> Choose all ascendants of node(2) 
    -> Ascendants of node(2) : [node(1)] 
    -> Insert a row with (parent_id = 1, child_id = 3, direct = False) 

3. To retrieve all descendants of node(1) 
    -> SELECT child_id FROM [table] WHERE parent_id = 1; 

4. To retrieve children of node(1) 
    -> SELECT child_id FROM [table] WHERE parent_id = 1 AND direct = True; 

5. To retrieve all ascendants of node(3) 
    -> SELECT parent_id FROM [table] WHERE child_id = 3; 

6. To retrieve parent of node(3) 
    -> SELECT parent_id FROM [table] WHERE child_id = 3 AND direct = True; 

+-----------+----------+--------+ 
| parent_id | child_id | direct | 
+-----------+----------+--------| 
|   1 |  2 | True | 
|   1 |  3 | False | 
|   2 |  3 | True | 
.... 
+-----------+----------+--------+ 
Index 1 on (parent_id, direct) 
Index 2 on (child_id, direct) 

Это approche имеет плохую производительность при обновлении отношений. Используйте на свой риск.

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