Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL:come trovare le foglie in un nodo specifico

Non c'è modo di farlo in una singola query. Anche se ci fosse, sarebbe probabilmente molto inefficiente.

Possiamo farlo con una procedura memorizzata e un ciclo. Con gli indici che hai aggiunto dovrebbe essere anche abbastanza veloce. Questo utilizza due tabelle che selezionano i nodi dalla tabella di input (A) e inseriscono il nodo e i loro figli in (B). Quindi scambia B con A e si ripete finché non esistono più nodi non foglia in A. La cosa bella è che le iterazioni del ciclo sarebbero tante quanti sono i livelli tra il nodo di input e l'ultimo nodo foglia, che nella maggior parte dei casi è probabilmente non così in profondità. Questa procedura memorizzata sarebbe più veloce che eseguirla esternamente nel codice.

Cordiali saluti, ho avuto difficoltà con la mia installazione nella gestione delle tabelle temporanee, se ricevi un "errore 2", rimuovi la parola chiave temporanea.

delimiter $$
drop procedure if exists GetLeafNodes $$
create procedure GetLeafNodes(nodeid int)
begin
declare N int default 1;

-- create two working sets of IDs, we'll go back and forth between these two sets
drop temporary table if exists A;
drop temporary table if exists B;
create temporary table A(node int, child int);
create temporary table B(node int, child int);

-- insert our single input node into the working set
insert into A values (null, nodeid);

while (N>0) do
  -- keep selecting child nodes for each node we are now tracking
  -- leaf nodes will end up with the child set to null
  insert into B
  select ifnull(A.child,A.node), tree.ID
    from A
    left outer join DATA_TREE as tree on A.child=tree.parent_id;

  -- now swap A and B
  rename table A to temp, B to A, temp to B;

  -- remove non-leaf nodes from table B
  delete from B;

  -- exit when there are no longer any non-leaf nodes in A
  set N=(select count(*) from A where child is not null);
end while;

-- now output our list of leaf nodes
select node from A;

drop temporary table A;
drop temporary table B;
end $$
DELIMITER ;
call GetLeafNodes(4);

Ho usato il seguente set di campioni per il test:

CREATE TABLE `DATA_TREE` (
  `ID` int(11) NOT NULL,
  `PARENT_ID` int(11) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `ID_UNIQUE` (`ID`),
  KEY `fk_DATA_TREE_1_idx` (`PARENT_ID`)
) ENGINE=InnoDB
;

insert into DATA_TREE values
(1,0),(2,1),(3,1),(4,1),(5,3),(6,3),(7,4),(8,4),(9,4),(10,6),(11,6),(12,7),(13,9),(14,9),(15,12),(16,12),(17,12),(18,14);