Изчислете дълбочината в модел родител-дете в MySQL

Как да изчисля дълбочината на възел в модел родител-дете под MySQL?

Ще ми трябва дълбочината, наред с други неща, за да създам отстъпа в моя списък (кодиран с PHP).


person Ivar    schedule 28.07.2009    source източник
comment
Току-що видях другия ви въпрос относно: преместване на възел в модела на вложените набори и изглежда, че сте получили някои много противоречиви отговори, така че мога да разбера разочарованието ви :-) Преместването на възела в модела на вложени набори всъщност е доста лесно (въпреки че в зависимост от размера на вашата маса може да е скъпо). Уведомете ме, ако все още се интересувате от това и мога да добавя отговора с обяснение.   -  person ChssPly76    schedule 28.07.2009
comment
Хаха, така е, доста се разочаровах от това. Намерих решение преди около седмица, което мисля, че трябва да работи, но все още не съм го внедрил. Но вложените набори няма да работят много добре за моите цели, тъй като вероятно ще има много ежедневни актуализации от много различни потребители, което означава много редове в таблицата. Поради тази причина ще опитам този модел на списък на съседство, който безопасно може да премести възел. палец нагоре   -  person Ivar    schedule 28.07.2009
comment
Успех с внедряването. Актуализирах отговора си, за да отразява модела на списъка на съседство.   -  person ChssPly76    schedule 29.07.2009


Отговори (3)


Това зависи от действителното внедряване на вашата йерархия в базата данни. Ако използвате модел на вложени набори (http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/) можете да извлечете пълния път от родител до дете чрез едно избиране.

Актуализация: Добре, тъй като ще използвате модел на списък със съседство, предлагам да съхранявате ниво на възел в таблицата. Не само ще ви даде дълбочината на възела в една заявка, но също така ще ви позволи да извлечете целия път до този възел в една заявка (въпреки че тази заявка трябва да бъде динамично генерирана):

SELECT n1.name AS lvl1, n2.name as lvl2, n3.name as lvl3, ..., nN.name as lvlN
  FROM nodes AS n1
  JOIN nodes AS n2 ON n2.parent_id = n1.id
  JOIN nodes AS n3 ON n3.parent_id = n2.id
  ...
  JOIN nodes AS nN ON nN.parent_id = n(N-1).id
WHERE nN.id = myChildNode;

Тъй като знаете, че вашият възел е на ниво N, няма нужда от леви съединявания и при подходящи индекси на id / parent_id това трябва да е сравнително бързо.
Недостатъкът на този подход е, че ще трябва да поддържате нивото на възел актуализирано по време на преместване на възел, но това трябва да е сравнително лесно и бързо, тъй като бихте го направили само за самия възел и неговите деца - не за по-голямата част от таблицата, както бихте направили с вложени набори.

person ChssPly76    schedule 28.07.2009
comment
Да, работил съм с вложени набори и знам как да изчисля дълбочината там, но сега имам нужда от дълбочината от модел родител-дете (очевидно само с колоните id и родител), а не от вложен набор. - person Ivar; 28.07.2009
comment
Между другото, това е дълбочината, която ме интересува (цяло число), а не пътя. - person Ivar; 28.07.2009
comment
Тогава говориш за модел на списък със съседство. Това е далеч от идеалното, за съжаление - ще ви трябват N избрани, за да финансирате дълбочината на възела на N-то ниво. - person ChssPly76; 28.07.2009
comment
Добре, значи бихте ми предложили да добавя друга колона към таблицата с име дълбочина? Но не виждам да го използвате във вашия пример. И в този случай дали ще бъде безопасно? Бих предпочел бърза система, която не променя няколко реда, ако е възможно. :) - person Ivar; 29.07.2009
comment
В моя пример дълбочината е N и вие генерирате една заявка с N обединения. Без да знаете дълбочината предварително, ще трябва да изпълните N заявки, за да направите същото. Ако случайно знаете максималната възможна дълбочина на цялата си йерархия (напр. тя не може да има повече от X нива), друг възможен компромис е да пренапишете горната заявка, като използвате X външни съединения. Няма да работи толкова добре, но няма да се налага да поддържате ниво на възел за всеки възел. - person ChssPly76; 29.07.2009

Това може да е стар въпрос, но просто искам да уведомя другите, че намерих решение преди няколко месеца. Наскоро писах за това тук: http://en.someotherdeveloper.com/articles/adjacency-list-model-with-depth-calculation/

person Ivar    schedule 07.11.2010

Ако искате просто да копирате и поставите, ето моят пример. Имам таблични проекти с полета ID и PARENT_ID.

DELIMITER $$
DROP FUNCTION IF EXISTS `getDepth` $$
CREATE FUNCTION `getDepth` (project_id INT) RETURNS int
BEGIN
    DECLARE depth INT;
    SET depth=1;

    WHILE project_id > 0 DO
        SELECT IFNULL(parent_id,-1) 
        INTO project_id 
        FROM ( SELECT parent_id FROM Projects WHERE id = project_id) t;

        IF project_id > 0 THEN
            SET depth = depth + 1;
        END IF;

    END WHILE;

    RETURN depth;

END $$
DELIMITER ;
person manuel    schedule 02.02.2016