Puxar esse resultado recursivamente é complicado (embora possível). No entanto, normalmente não é muito eficiente e há um muito melhor maneira de resolver este problema.
Basicamente, você aumenta a tabela com uma coluna extra que traça a árvore até o topo - vou chamá-la de "Upchain". É apenas uma longa string que se parece com isso:
name | id | parent_id | upchain
root1 | 1 | NULL | 1:
root2 | 2 | NULL | 2:
root1sub1 | 3 | 1 | 1:3:
root1sub2 | 4 | 1 | 1:4:
root2sub1 | 5 | 2 | 2:5:
root2sub2 | 6 | 2 | 2:6:
root1sub1sub1 | 7 | 3 | 1:3:7:
É muito fácil manter esse campo atualizado usando um gatilho na tabela. (Desculpas pela terminologia, mas sempre fiz isso com o SQL Server). Toda vez que você adiciona ou exclui um registro, ou atualiza o campo parent_id, você só precisa atualizar o campo upchain nessa parte da árvore. Esse é um trabalho trivial porque você apenas pega o upchain do registro pai e acrescenta o id do registro atual. Todos os registros filho são facilmente identificados usando LIKE para verificar registros com a string inicial em sua cadeia ascendente.
O que você está fazendo efetivamente é trocar um pouco de atividade de gravação extra por um grande salvando quando você vem para ler os dados.
Quando você deseja selecionar uma ramificação completa na árvore, é trivial. Suponha que você queira a ramificação sob o nó 1. O nó 1 tem um upchain '1:' para que você saiba que qualquer nó na ramificação da árvore sob esse nó deve ter um upchain começando '1:...'. Então você só faz isso:
SELECT *
FROM table
WHERE upchain LIKE '1:%'
Isso é extremamente rápido (indexe o campo upchain, é claro). Como bônus, também torna muitas atividades extremamente simples, como encontrar árvores parciais, nível dentro da árvore, etc.
Eu usei isso em aplicativos que rastreiam grandes hierarquias de relatórios de funcionários, mas você pode usá-lo para praticamente qualquer estrutura de árvore (divisão de peças, etc.)
Observações (para quem estiver interessado):
- Eu não dei um passo a passo do código SQL, mas uma vez que você entenda o princípio, é bem simples de implementar. Não sou um grande programador, então falo por experiência própria.
- Se você já tiver dados na tabela, precisará fazer uma atualização única para sincronizar os upchains inicialmente. Novamente, isso não é difícil, pois o código é muito semelhante ao código UPDATE nos gatilhos.
- Essa técnica também é uma boa maneira de identificar referências circulares que podem ser difíceis de identificar.