A consulta a seguir permitirá que você abra qualquer caminho (ou conjuntos de caminhos) aproveitando a cláusula do SQL e o group_concat função.
Veja a seguir a definição da tabela e os dados de exemplo que usei:
drop table nested_set;
CREATE TABLE nested_set (
id INT,
name VARCHAR(20) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL
);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (1,'HEAD',1,28);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (2,'A',2,3);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (3,'B',4,17);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (4,'B1',5,10);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (5,'B1.1',6,7);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (6,'B1.2',8,9);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (7,'B2',11,16);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (8,'B2.1',12,13);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (9,'B2.2',14,15);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (10,'C',18,25);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (11,'C1',19,20);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (12,'C2',21,22);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (13,'C3',23,24);
INSERT INTO nested_set (id, name, lft, rgt) VALUES (14,'D',26,27);
A consulta a seguir fornece a árvore inteira (exceto a HEAD):
SELECT
node.id
, node.lft
, node.rgt
, node.name
, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS path
, (COUNT(parent.lft) - 1) AS depth
FROM nested_set AS node
inner join nested_set AS parent
on node.lft BETWEEN parent.lft AND parent.rgt
where parent.lft > 1
GROUP BY node.id
Com uma saída do seguinte quando executado em relação aos dados de amostra:
+------+-----+-----+------+-----------+-------+
| id | lft | rgt | name | path | depth |
+------+-----+-----+------+-----------+-------+
| 2 | 2 | 3 | A | A | 0 |
| 3 | 4 | 17 | B | B | 0 |
| 4 | 5 | 10 | B1 | B/B1 | 1 |
| 5 | 6 | 7 | B1.1 | B/B1/B1.1 | 2 |
| 6 | 8 | 9 | B1.2 | B/B1/B1.2 | 2 |
| 7 | 11 | 16 | B2 | B/B2 | 1 |
| 8 | 12 | 13 | B2.1 | B/B2/B2.1 | 2 |
| 9 | 14 | 15 | B2.2 | B/B2/B2.2 | 2 |
| 10 | 18 | 25 | C | C | 0 |
| 11 | 19 | 20 | C1 | C/C1 | 1 |
| 12 | 21 | 22 | C2 | C/C2 | 1 |
| 13 | 23 | 24 | C3 | C/C3 | 1 |
| 14 | 26 | 27 | D | D | 0 |
+------+-----+-----+------+-----------+-------+
As seguintes adições à consulta acima fornecerão o controle necessário para abrir as várias seções:
having
depth = 0
or ('<PATH_TO_OPEN>' = left(path, length('<PATH_TO_OPEN>'))
and depth = length('<PATH_TO_OPEN>') - length(replace('<PATH_TO_OPEN>', '/', '')) + 1)
A cláusula having aplica filtros aos resultados do grupo por consulta. A parte "profundidade =0" é para garantir que sempre tenhamos nós de menu base (A, B, C e D). A próxima parte é a parte que controla quais nós estão abertos. Ele compara o caminho dos nós com um caminho definido que você deseja abrir ('') para ver se ele corresponde e também garante que ele só abra nível no caminho. A seção inteira ou com a lógica '' pode ser duplicada e adicionada conforme necessário para abrir vários caminhos conforme necessário. Certifique-se de que '' não termine em uma barra final (/).
A seguir estão alguns exemplos de saída para mostrar como você construiria consultas para obter as saídas desejadas:
=========Open B==========
SELECT
node.id
, node.lft
, node.rgt
, node.name
, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS path
, (COUNT(parent.lft) - 1) AS depth
FROM nested_set AS node
inner join nested_set AS parent
on node.lft BETWEEN parent.lft AND parent.rgt
where parent.lft > 1
GROUP BY node.id
having
depth = 0
or ('B' = left(path, length('B'))
and depth = length('B') - length(replace('B', '/', '')) + 1)
+------+-----+-----+------+------+-------+
| id | lft | rgt | name | path | depth |
+------+-----+-----+------+------+-------+
| 2 | 2 | 3 | A | A | 0 |
| 3 | 4 | 17 | B | B | 0 |
| 4 | 5 | 10 | B1 | B/B1 | 1 |
| 7 | 11 | 16 | B2 | B/B2 | 1 |
| 10 | 18 | 25 | C | C | 0 |
| 14 | 26 | 27 | D | D | 0 |
+------+-----+-----+------+------+-------+
=========Open B and B/B1==========
SELECT
node.id
, node.lft
, node.rgt
, node.name
, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS path
, (COUNT(parent.lft) - 1) AS depth
FROM nested_set AS node
inner join nested_set AS parent
on node.lft BETWEEN parent.lft AND parent.rgt
where parent.lft > 1
GROUP BY node.id
having
depth = 0
or ('B' = left(path, length('B'))
and depth = length('B') - length(replace('B', '/', '')) + 1)
or ('B/B1' = left(path, length('B/B1'))
and depth = length('B/B1') - length(replace('B/B1', '/', '')) + 1)
+------+-----+-----+------+-----------+-------+
| id | lft | rgt | name | path | depth |
+------+-----+-----+------+-----------+-------+
| 2 | 2 | 3 | A | A | 0 |
| 3 | 4 | 17 | B | B | 0 |
| 4 | 5 | 10 | B1 | B/B1 | 1 |
| 5 | 6 | 7 | B1.1 | B/B1/B1.1 | 2 |
| 6 | 8 | 9 | B1.2 | B/B1/B1.2 | 2 |
| 7 | 11 | 16 | B2 | B/B2 | 1 |
| 10 | 18 | 25 | C | C | 0 |
| 14 | 26 | 27 | D | D | 0 |
+------+-----+-----+------+-----------+-------+
=========Open B and B/B1 and C==========
SELECT
node.id
, node.lft
, node.rgt
, node.name
, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS path
, (COUNT(parent.lft) - 1) AS depth
FROM nested_set AS node
inner join nested_set AS parent
on node.lft BETWEEN parent.lft AND parent.rgt
where parent.lft > 1
GROUP BY node.id
having
depth = 0
or ('B' = left(path, length('B'))
and depth = length('B') - length(replace('B', '/', '')) + 1)
or ('B/B1' = left(path, length('B/B1'))
and depth = length('B/B1') - length(replace('B/B1', '/', '')) + 1)
or ('C' = left(path, length('C'))
and depth = length('C') - length(replace('C', '/', '')) + 1)
+------+-----+-----+------+-----------+-------+
| id | lft | rgt | name | path | depth |
+------+-----+-----+------+-----------+-------+
| 2 | 2 | 3 | A | A | 0 |
| 3 | 4 | 17 | B | B | 0 |
| 4 | 5 | 10 | B1 | B/B1 | 1 |
| 5 | 6 | 7 | B1.1 | B/B1/B1.1 | 2 |
| 6 | 8 | 9 | B1.2 | B/B1/B1.2 | 2 |
| 7 | 11 | 16 | B2 | B/B2 | 1 |
| 10 | 18 | 25 | C | C | 0 |
| 11 | 19 | 20 | C1 | C/C1 | 1 |
| 12 | 21 | 22 | C2 | C/C2 | 1 |
| 13 | 23 | 24 | C3 | C/C3 | 1 |
| 14 | 26 | 27 | D | D | 0 |
+------+-----+-----+------+-----------+-------+
É sobre isso. você apenas continua duplicando isso ou seção para cada caminho que você precisa abrir.
Consulte http://mikehillyer.com/articles/managing-hierarchical-data -in-mysql/ caso você precise de informações gerais sobre como trabalhar com conjuntos aninhados no MySQL.
Deixe-me saber se você tiver alguma dúvida.
HTH,
-Dipin