sql >> Base de Datos >  >> RDS >> Mysql

MySQL Tree ordenado por padre e hijo

Hay otras formas de organizar datos jerárquicos además de los métodos que se muestran en el blog de Mike Hillyer. Me gusta usar un método que llamo tabla de cierre transitiva o mesa de cierre para abreviar. En este diseño, almacena cada ruta a través de la jerarquía, como pares de ascendiente/descendiente.

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

Tenga en cuenta que este conjunto incluye incluso las "rutas" de longitud cero, es decir, un elemento de menú es un "principal" de sí mismo.

Ahora puede unirse a cada elemento del menú m a cada su conjunto de ancestros a , uniéndose a rutas donde m es el descendente. Desde allí, vuelve a unirte al elemento del menú o que está en el conjunto de ancestros, y puedes acceder al order .

Use GROUP_CONCAT() para hacer una cadena de "migas de pan" del order de cada uno en la cadena de ancestros, y esto se convierte en una cadena que puede ordenar para obtener el orden de menú que desea.

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           |
+----+----------+-------+-------------+

Tenga en cuenta que las migas de pan se ordenan como una cadena, por lo que si tiene algún order números con 2 o 3 dígitos, obtendrá resultados irregulares. Asegúrate de que tu order todos los números tienen el mismo número de dígitos.

Como alternativa, simplemente puede almacenar las cadenas de migas de pan en su tabla de menú original:

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

Entonces puedes hacer una consulta más simple:

SELECT * FROM menu ORDER BY breadcrumbs;

Pero luego depende de usted recalcular manualmente todas las cadenas de migas de pan afectadas, si alguna vez cambia el orden de los elementos del menú.