Pergunta

Eu tenho um problema de árvore / ancestral / consulta Eu não sou capaz de resolver:

Eu não detenham uma participação tabela de dados de menu e uma tabela contendo todos os antepassados ??de menu:

table menu               table ancestors
+-----+------------+--------+     +---------+--------------+-------+
| id  |      title | active |     | menu_id |  ancestor_id | level |
+-----+------------+--------+     +---------+--------------+-------+
|   1 |       Home |      0 |     |       1 |            0 |     0 |
|   2 |       News |      0 |     |       2 |            1 |     1 |
|   3 |        Foo |      0 |     |       3 |            2 |     2 |
|   4 |        Bar |      1 |     |       3 |            1 |     1 |
|   5 |  Downloads |      1 |     |       4 |            3 |     3 |
+-----+------------+--------+     |       4 |            2 |     2 |
                                  |       4 |            1 |     1 |
                                  |       5 |            1 |     1 |
                                  +---------+--------------+-------+

Eu recebo todas as entradas do menu de ativos com os seus antepassados ??facilmente com:

 SELECT menu.id, menu.title, GROUP_CONCAT(ancestors.ancestor_id) as ancestors
FROM menu, ancestors
WHERE menu.active = 1
GROUP BY (menu.id);

 +----+-----------+----------+
 | id |     title |ancestors |
 +----+-----------+----------+
 |  4 |       Bar | 3,2,1    | 
 |  5 | Downloads | 1        |
 +----+-----------+----------+

Mas como posso obter todos os os para a árvore antepassados ??necessárias, também? Em meu resultado que eu precisaria a entrada Foo and News para que eu recebo uma árvore consistente. Deve olhar como este:

 +----+-----------+----------+
 | id |     title |ancestors |
 +----+-----------+----------+
 |  2 |      News | 1        | 
 |  3 |       Foo | 2,1      | 
 |  4 |       Bar | 3,2,1    | 
 |  5 | Downloads | 1        |
 +----+-----------+----------+

Como tem a consulta para ser como?

Foi útil?

Solução

Quando eu fizer isso, eu estruturar tabela de ancestors ligeiramente diferente. Em vez de level, eu armazenar pathlength. Também armazenar uma linha para cada item de menu para apontar para si próprio, com um comprimento de caminho de 0.

+---------+--------------+------------+
| menu_id |  ancestor_id | pathlength |
+---------+--------------+------------+
|       1 |            1 |          0 |
|       2 |            2 |          0 |
|       3 |            3 |          0 |
|       4 |            4 |          0 |
|       5 |            5 |          0 |
|       2 |            1 |          1 |
|       3 |            2 |          2 |
|       3 |            1 |          1 |
|       4 |            3 |          3 |
|       4 |            2 |          2 |
|       4 |            1 |          1 |
|       5 |            1 |          1 |
+---------+--------------+------------+

Estas entradas "reflexiva" permitir-lhe juntar-se o conjunto de itens de menu ativas para a mesa de encerramento. Alterar nível para pathlength permite excluir as entradas reflexivas do conjunto dos antepassados.

Agora você pode consultar todos os itens de menu que são ancestrais dos itens do menu "activos", incluindo os itens de menu activa-se:

SELECT a2.menu_id, m2.title, GROUP_CONCAT(a2.ancestor_id) AS ancestors
FROM menu m1
JOIN ancestors a1 ON (m1.id = a1.menu_id)
JOIN ancestors a2 ON (a1.ancestor_id = a2.menu_id AND a2.pathlength > 0)
JOIN menu m2 ON (a2.menu_id = m2.id)
WHERE m1.active = 1
GROUP BY a2.menu_id;

Resultado:

+---------+-----------+-----------+
| menu_id | title     | ancestors |
+---------+-----------+-----------+
|       2 | News      | 1         | 
|       3 | Foo       | 2,1       | 
|       4 | Bar       | 3,2,1     | 
|       5 | Downloads | 1         | 
+---------+-----------+-----------+
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top