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

MySQL Tree ordinato per genitore e figlio

Esistono altri modi per organizzare i dati gerarchici oltre ai metodi mostrati nel blog di Mike Hillyer. Mi piace usare un metodo che chiamo tabella di chiusura transitiva o tabella di chiusura in breve. In questo design, memorizzi ogni percorso attraverso la gerarchia, come coppie antenato/discendente.

create table closure (
    ancestor int,
    descendant int,
    length int,
    primary key (ancestor,descendant),
    key (descendant,ancestor)
);
insert into closure values
(1,1,0),
(1,3,1),
(1,4,2),
(1,5,3),
(2,2,0),
(3,3,0),
(3,4,1),
(3,5,2),
(4,4,0),
(4,5,1),
(5,5,0);

Nota che questo set include anche i "percorsi" di lunghezza zero, ovvero una voce di menu è un "genitore" di se stessa.

Ora puoi unirti a ciascuna voce di menu m a ogni suo insieme di antenati a , unendosi ai percorsi dove m è il discendente. Da lì, torna alla voce di menu o che si trova nell'insieme degli antenati e puoi accedere all'order .

Usa GROUP_CONCAT() per creare una stringa di "breadcrumbs" dall'order di ciascuno nella catena di antenati, e questa diventa una stringa che puoi ordinare per ottenere l'ordine del menu desiderato.

SELECT m.*, GROUP_CONCAT(o.`order` ORDER BY a.length DESC) AS breadcrumbs
FROM menu AS m
INNER JOIN closure AS a ON a.descendant = m.id
INNER JOIN menu AS o ON a.ancestor = o.id
GROUP BY m.id
ORDER BY breadcrumbs;

+----+----------+-------+-------------+
| id | name     | order | breadcrumbs |
+----+----------+-------+-------------+
|  1 | Father1  |     0 | 0           |
|  3 | Son      |     0 | 0,0         |
|  4 | Child    |     1 | 0,0,1       |
|  5 | Grandson |     2 | 0,0,1,2     |
|  2 | Father2  |     1 | 1           |
+----+----------+-------+-------------+

Nota che i breadcrumb vengono ordinati come una stringa, quindi se hai qualche order numeri con 2 o 3 cifre, otterrai risultati irregolari. Assicurati che il tuo order i numeri hanno tutti lo stesso numero di cifre.

In alternativa, puoi semplicemente memorizzare le stringhe di breadcrumb nella tabella del menu originale:

ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.

Quindi puoi fare una query più semplice:

SELECT * FROM menu ORDER BY breadcrumbs;

Ma poi sta a te ricalcolare manualmente tutte le stringhe breadcrumb interessate, se dovessi modificare l'ordine delle voci di menu.