Ada cara lain untuk mengatur data hierarkis selain metode yang ditampilkan di blog Mike Hillyer. Saya suka menggunakan metode yang saya sebut tabel penutupan transitif atau meja penutup untuk jangka pendek. Dalam desain ini, Anda menyimpan setiap jalur melalui hierarki, sebagai pasangan ancestor/descendant.
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);
Perhatikan bahwa set ini bahkan menyertakan "jalur" dengan panjang nol, yaitu item menu adalah "induk" dari dirinya sendiri.
Sekarang Anda dapat bergabung dengan setiap item menu m
untuk setiap set leluhurnya a
, dengan bergabung ke jalur di mana m
adalah keturunan. Dari sana, gabung kembali ke item menu o
yang ada di set nenek moyang, dan Anda dapat mengakses order
.
Gunakan GROUP_CONCAT() untuk membuat string "remah roti" dari order
masing-masing dalam rantai nenek moyang, dan ini menjadi string yang dapat Anda urutkan untuk mendapatkan urutan menu yang Anda inginkan.
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 |
+----+----------+-------+-------------+
Perhatikan bahwa remah roti diurutkan sebagai string, jadi jika Anda memiliki beberapa order
angka dengan 2 atau 3 digit, Anda akan mendapatkan hasil yang tidak teratur. Pastikan order
semua nomor memiliki jumlah digit yang sama.
Sebagai alternatif, Anda cukup menyimpan string remah roti di tabel menu asli Anda:
ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.
Kemudian Anda dapat melakukan kueri yang lebih sederhana:
SELECT * FROM menu ORDER BY breadcrumbs;
Namun terserah Anda untuk menghitung ulang secara manual semua string breadcrumb yang terpengaruh, jika Anda pernah mengubah urutan item menu.