Pergunta

Como calcular a profundidade de um nó em um modelo pai-filho sob o MySQL?

Vou precisar da profundidade para, entre outras coisas, criar o recuo na minha lista (codificado com PHP).

Foi útil?

Solução 2

Isso pode ser uma pergunta antiga, mas eu só quero que os outros saibam que encontrei uma solução há alguns meses. Eu escrevi recentemente sobre isso aqui: http://en.beroterdeveloper.com/articles/adjacency-list-model-with-depth-calculation/

Outras dicas

Isso depende da implementação real de sua hierarquia no banco de dados. Se você estiver usando o modelo de conjuntos aninhados (http://mikehillyer.com/articles/managing-hierchical-data-in-mysql/) Você pode recuperar o caminho completo para pai para filho por meio de uma única seleção.

Atualizar: OK, já que você está indo com o modelo de lista de adjacência, sugiro armazenar o nível do nó na tabela. Não apenas lhe dará a profundidade do nó em uma consulta, mas também permitirá que você recupere todo o caminho para esse nó em uma consulta (embora que a consulta teria que ser gerada dinamicamente):

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;

Como você sabe que seu nó está no nível n, não há necessidade de junções à esquerda e, dados os índices apropriados no ID / Parent_ID, isso deve ser razoavelmente rápido.
A desvantagem dessa abordagem é que você terá que manter o nível do nó atualizado durante os movimentos do nó, mas isso deve ser razoavelmente direto e rápido, como você só faria isso pelo próprio nó e seus filhos - não para a maioria da tabela como Você faria com conjuntos aninhados.

Se você quiser apenas copiar a pasta aqui está o meu exemplo. Eu tenho projetos de tabela com ID e arquivamentos parentais.

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 ;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top