Mysql
 sql >> Baza danych >  >> RDS >> Mysql

MySQL:Jak znaleźć liście w konkretnym węźle

Nie można tego zrobić w jednym zapytaniu. Nawet gdyby tak było, prawdopodobnie byłoby to bardzo nieefektywne.

Możemy to zrobić za pomocą procedury składowanej i pętli. Dzięki dodanym indeksom powinno to być również dość szybkie. Wykorzystuje to dwie tabele wybierające węzły z tabeli wejściowej (A) i wstawiające węzeł i jego dzieci do (B). Następnie zamienia B na A i powtarza, aż nie będzie więcej węzłów innych niż liście w A. Fajną rzeczą jest to, że iteracje pętli będą tylko tyle, ile ich poziomów między węzłem wejściowym a ostatnim węzłem liścia, który w większości przypadków jest prawdopodobnie nie tak głęboko. Ta procedura składowana byłaby szybsza niż robienie tego zewnętrznie w kodzie.

FYI Miałem trudności z moją instalacją obsługującą tabele tymczasowe, jeśli pojawi się „błąd 2”, usuń słowo kluczowe tymczasowe.

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);

Do testów użyłem następującego zestawu próbek:

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);



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQLAlchemy i UnicodeDecodeError

  2. mysqldump tworzenie kopii zapasowych i przywracanie na zdalnym serwerze

  3. Klucze obce w MySQL?

  4. Status pokazu MySQL - połączenia aktywne czy całkowite?

  5. mysqld_safe Katalog '/var/run/mysqld' dla pliku gniazda UNIX nie istnieje