Recursão do Mysql?

Considere uma tabela como esta:

folders_table ----------------------- INT id_folder INT id_folder_parent VARCHAR folder_name 

Que armazena uma estrutura de diretórios simples. Como eu poderia obter todos os subdiretórios de um diretório com uma única consulta SELECT?

É possível, mas você precisa mudar sua estrutura de database; Depois que as alterações forem feitas, você poderá recuperar uma tree de qualquer profundidade em uma consulta. As consultas são um pouco mais complexas, mas ainda são bem diretas.

  • Armazenando dados hierárquicos em um database (SitePoint) – este artigo é passo a passo, muito claro.
  • Gerenciando Dados Hierárquicos no MySQL – não tão claro quanto o acima.

Com a estrutura da tabela que você mostrou, isso não pode ser feito com o MySQL, pois ele não suporta consultas recursivas

Com MySql / MariaDB você pode usar o mecanismo Open Query Graph ( http://openquery.com/graph/doc ) que é um plugin mysql que permite criar uma tabela especial onde você coloca os relacionamentos, basicamente parentId e childId.

A mágica é que você consulta essa tabela com uma trava de coluna especial, dependendo do valor passado na consulta, dirá ao mecanismo OQGRAPH qual comando executar. Veja os documentos para detalhes.

Ele lida não apenas com trees (relações 1-n recursivas), mas grava estruturas de dados (relações nm recursivas) com peso (pense, por exemplo, que você quer armazenar empresas, uma empresa pode ter várias subsidiárias e também vários acionistas).

A outra opção é armazenar a profundidade do nó e manter um identificador para o caminho completo de cada nó e usar ambos como critérios.

A maneira como eu armazeno nós XML em um database relacional é a seguinte:

 SELECT id,value FROM element e1 INNER JOIN element e2 ON (e2.id=e1.parent_id AND name='friend') WHERE e1.depth>4 AND e1.path like 'root[1]/users[1]/user:dana[1]/public[1]%' 

Neste exemplo, eu tenho um campo para o nome do nó e um interator em colchetes para nós duplicados com o mesmo nome de nó em cada nível na tree.

Quando você insere cada nó, é necessário calcular o caminho completo seguindo os pais até o nó raiz ( parent_id IS NULL ) anexando cada nível em uma matriz e, ao mesmo tempo, armazenando a profundidade do caminho.

É sempre bom em qualquer tipo de hierarquia armazenada em um database ter uma representação visual e access fácil a qualquer caminho, já que seguir a tree em cada solicitação pode ser caro, especialmente com o mysql que não possui nenhuma syntax SQL recursiva direta.

O esquema da esquerda / direita de armazenar nós em uma hierarquia (lista de adjacências de conjunto nested) é muito perigoso em minha mente e muito mais pode dar errado com esse tipo de esquema, por um lado, é muito complicado de gerenciar.

1 、 criar uma nova tabela. tree_folder(id, id_folder, tree_id) 2 、 crie uma nova tabela. tree(id, tree_json)

A tabela da tree mantém um nó da tree inteira. Por exemplo, a seguinte tree com um nó raiz 1 .

 { "folder_id": 1, "parent_folder_id": 0, "children": [ { "folder_id": 10, "parent_folder_id": 1, "children": null }, { "folder_id": 11, "parent_folder_id": 2, "children": null } ] } 

A tabela contém esta linha.

 [id, tree_json] [1, "xxxxx"] 

Em seguida, mantenha a relação entre o nó e a tree. Como você pode ver, a tree contém o nó 1 , 10 , 11 . Então nós temos a tabela tree_folder .

 [id, folder_id, tree_id] [1, 1 , 1] [2, 10 , 1] [3, 11 , 1] 

Quando você precisa pegar a tree da pasta 10 . é só pegar a tree e depois distribuí-la no seu programa.

Desta forma, você apenas faz recursion na memory ao invés do mysql.

Isso é você deve manter a estrutura quando gravar os dados, mas a consulta é fácil e rápida. Se a consulta é freqüente, isso funciona bem. Mas se a gravação é freqüente, basta usar um cache em vez desse método.