Mike Hillyerのブログに示されている方法以外に、階層データを整理する方法は他にもあります。 推移閉包テーブルと呼ぶメソッドを使用するのが好きです または略してクロージャーテーブル。この設計では、階層内のすべてのパスを祖先/子孫のペアとして格納します。
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);
このセットには、長さがゼロの「パス」も含まれていることに注意してください。つまり、メニュー項目はそれ自体の「親」です。
これで、各メニュー項目m
に参加できます 祖先のすべてのセットにa
、m
のパスに参加する デスカンダントです。そこから、メニュー項目o
に戻ります これは祖先のセットに含まれており、order
にアクセスできます。 。
GROUP_CONCAT()を使用して、order
から「ブレッドクラム」の文字列を作成します 祖先のチェーン内のそれぞれの文字列になります。これは、必要なメニュー順序を取得するために並べ替えることができる文字列になります。
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 |
+----+----------+-------+-------------+
ブレッドクラムは文字列として並べ替えられるため、order
がある場合は 2桁または3桁の数字の場合、不規則な結果が得られます。 order
を確認してください 数字はすべて同じ桁数です。
別の方法として、パンくずリストの文字列を元のメニューテーブルに保存することもできます。
ALTER TABLE menu ADD COLUMN breadcrumbs VARCHAR(255);
UPDATE menu SET breadcrumbs = '0,0,1,2' WHERE id = 5;
etc.
次に、より簡単なクエリを実行できます:
SELECT * FROM menu ORDER BY breadcrumbs;
ただし、メニュー項目の順序を変更した場合は、影響を受けるすべてのブレッドクラム文字列を手動で再計算するのはあなた次第です。