Có những cách khác để tổ chức dữ liệu phân cấp bên cạnh các phương pháp được hiển thị trong blog của Mike Hillyer. Tôi thích sử dụng phương pháp mà tôi gọi là bảng đóng bắc cầu hay gọi tắt là bảng đóng cửa. Trong thiết kế này, bạn lưu trữ mọi đường dẫn thông qua hệ thống phân cấp, dưới dạng các cặp tổ tiên / con cháu.
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);
Lưu ý rằng tập hợp này bao gồm cả "đường dẫn" có độ dài bằng 0, tức là một mục menu là "cha" của chính nó.
Bây giờ bạn có thể tham gia từng mục menu m
cho mọi tập hợp tổ tiên của nó a
, bằng cách tham gia vào các đường dẫn tại đó m
là chất làm khô. Từ đó, hãy quay lại mục menu o
nằm trong tập hợp tổ tiên và bạn có thể truy cập vào order
.
Sử dụng GROUP_CONCAT () để tạo một chuỗi "breadcrumbs" từ order
của mỗi thứ trong chuỗi tổ tiên và đây sẽ trở thành một chuỗi mà bạn có thể sắp xếp theo thứ tự thực đơn mà bạn muốn.
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 |
+----+----------+-------+-------------+
Lưu ý rằng breadcrumbs sắp xếp như một chuỗi, vì vậy nếu bạn có một số order
số có 2 hoặc 3 chữ số, bạn sẽ nhận được kết quả không đều. Đảm bảo order
của bạn tất cả các số đều có cùng số chữ số.
Thay vào đó, bạn có thể chỉ cần lưu trữ các chuỗi breadcrumbs trong bảng menu ban đầu của mình:
ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.
Sau đó, bạn có thể thực hiện một truy vấn đơn giản hơn:
SELECT * FROM menu ORDER BY breadcrumbs;
Nhưng sau đó, bạn phải tính toán lại theo cách thủ công tất cả các chuỗi breadcrumb bị ảnh hưởng, nếu bạn thay đổi thứ tự của các mục trong menu.