SUB-ÁRVORE DENTRO DE UMA ÁRVORE no MySQL
No meu MYSQL Database COMPANY
, tenho uma Table: Employee
associação recursiva, um funcionário pode ser chefe de outro funcionário. A self relationship of kind (SuperVisor (1)- SuperVisee (∞) )
.
Consulta para criar tabela:
CREATE TABLE IF NOT EXISTS `Employee` (
`SSN` varchar(64) NOT NULL,
`Name` varchar(64) DEFAULT NULL,
`Designation` varchar(128) NOT NULL,
`MSSN` varchar(64) NOT NULL,
PRIMARY KEY (`SSN`),
CONSTRAINT `FK_Manager_Employee`
FOREIGN KEY (`MSSN`) REFERENCES Employee(SSN)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Eu inseri um conjunto de tuplas (Query):
INSERT INTO Employee VALUES
("1", "A", "OWNER", "1"),
("2", "B", "BOSS", "1"), # Employees under OWNER
("3", "F", "BOSS", "1"),
("4", "C", "BOSS", "2"), # Employees under B
("5", "H", "BOSS", "2"),
("6", "L", "WORKER", "2"),
("7", "I", "BOSS", "2"),
# Remaining Leaf nodes
("8", "K", "WORKER", "3"), # Employee under F
("9", "J", "WORKER", "7"), # Employee under I
("10","G", "WORKER", "5"), # Employee under H
("11","D", "WORKER", "4"), # Employee under C
("12","E", "WORKER", "4")
As linhas inseridas têm o seguinte Tree-Hierarchical-Relationship :
A <---ROOT-OWNER
/|\
/ A \
B F
//| \ \
// | \ K
/ | | \
I L H C
/ | / \
J G D E
Eu escrevi uma consulta para encontrar o relacionamento:
SELECT SUPERVISOR.name AS SuperVisor,
GROUP_CONCAT(SUPERVISEE.name ORDER BY SUPERVISEE.name ) AS SuperVisee,
COUNT(*)
FROM Employee AS SUPERVISOR
INNER JOIN Employee SUPERVISEE ON SUPERVISOR.SSN = SUPERVISEE.MSSN
GROUP BY SuperVisor;
E a saída é:
+------------+------------+----------+
| SuperVisor | SuperVisee | COUNT(*) |
+------------+------------+----------+
| A | A,B,F | 3 |
| B | C,H,I,L | 4 |
| C | D,E | 2 |
| F | K | 1 |
| H | G | 1 |
| I | J | 1 |
+------------+------------+----------+
6 rows in set (0.00 sec)
[ PERGUNTA ]
Em vez de uma árvore hierárquica completa, preciso SUB-TREE
de um ponto (seletivo), por exemplo:
Se B
o argumento de entrada for, a saída deve ser como abaixo ...
+------------+------------+----------+
| SuperVisor | SuperVisee | COUNT(*) |
+------------+------------+----------+
| B | C,H,I,L | 4 |
| C | D,E | 2 |
| H | G | 1 |
| I | J | 1 |
+------------+------------+----------+
Por favor me ajude nisso. Se não for uma consulta, um procedimento armazenado pode ser útil.
Eu tentei, mas todos os esforços foram inúteis!
Eu já abordei algo dessa natureza usando Stored Procedures : Encontre o nível mais alto de um campo hierárquico: com vs sem CTEs (24 de outubro de 2011)
Se você olhar no meu post, você pode usar as funções GetAncestry e GetFamilyTree como um modelo para percorrer a árvore a partir de qualquer ponto.
ATUALIZAÇÃO 2012-12-11 12:11 EDT
Eu olhei para o meu código do meu post . Eu escrevi a função armazenada para você:
Ele realmente funciona. Aqui está uma amostra:
Há apenas uma captura. Eu adicionei uma linha extra para o proprietário
Aqui estão os dados
O que você está usando é chamado de Modelo de Lista de Adjacência . Tem muitas limitações. Você terá problemas quando quiser excluir/inserir um nó em um local específico. É melhor você usar o modelo de conjunto aninhado .
Há uma explicação detalhada . Infelizmente o artigo no mysql.com não existe mais.