MySQLでのメニュー表から一貫性のあるメニューツリーのデータを取得
-
13-09-2019 - |
質問
私は私が解決することができないんだけどツリー/祖先/クエリの問題を抱えています
私は、メニューデータとメニューのすべての祖先を含むテーブルを保持するテーブルを持っています:
table menu table ancestors
+-----+------------+--------+ +---------+--------------+-------+
| id | title | active | | menu_id | ancestor_id | level |
+-----+------------+--------+ +---------+--------------+-------+
| 1 | Home | 0 | | 1 | 0 | 0 |
| 2 | News | 0 | | 2 | 1 | 1 |
| 3 | Foo | 0 | | 3 | 2 | 2 |
| 4 | Bar | 1 | | 3 | 1 | 1 |
| 5 | Downloads | 1 | | 4 | 3 | 3 |
+-----+------------+--------+ | 4 | 2 | 2 |
| 4 | 1 | 1 |
| 5 | 1 | 1 |
+---------+--------------+-------+
私は簡単に自分の祖先を持つすべてのアクティブなメニュー項目を取得します:
SELECT menu.id, menu.title, GROUP_CONCAT(ancestors.ancestor_id) as ancestors
FROM menu, ancestors
WHERE menu.active = 1
GROUP BY (menu.id);
+----+-----------+----------+
| id | title |ancestors |
+----+-----------+----------+
| 4 | Bar | 3,2,1 |
| 5 | Downloads | 1 |
+----+-----------+----------+
しかし、私はすべてのツリーに必要な先祖を得ることができますどのように、あまりにも?私は一貫ツリーを得るように、私の結果では、私は、エントリfooとニュースを必要とするだろう。それは次のようになります:
+----+-----------+----------+
| id | title |ancestors |
+----+-----------+----------+
| 2 | News | 1 |
| 3 | Foo | 2,1 |
| 4 | Bar | 3,2,1 |
| 5 | Downloads | 1 |
+----+-----------+----------+
どのようなものにするクエリを持っている?
解決
私はこれを行うと、私は少し異なりancestors
テーブルを構築します。代わりにlevel
、私はpathlength
を格納します。また、0の経路長で、それ自体を指すように各メニュー項目の行を格納する。
+---------+--------------+------------+
| menu_id | ancestor_id | pathlength |
+---------+--------------+------------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 0 |
| 2 | 1 | 1 |
| 3 | 2 | 2 |
| 3 | 1 | 1 |
| 4 | 3 | 3 |
| 4 | 2 | 2 |
| 4 | 1 | 1 |
| 5 | 1 | 1 |
+---------+--------------+------------+
これらの「再帰」エントリーはあなたが閉鎖テーブルにアクティブなメニューアイテムのセットに参加することができます。光路長にレベルを変更すると、あなたは先祖のセットから再帰エントリを除外することができます。
これは、アクティブなメニュー項目自身を含む「アクティブ」のメニュー項目の祖先であるすべてのメニュー項目を照会することができます:
SELECT a2.menu_id, m2.title, GROUP_CONCAT(a2.ancestor_id) AS ancestors
FROM menu m1
JOIN ancestors a1 ON (m1.id = a1.menu_id)
JOIN ancestors a2 ON (a1.ancestor_id = a2.menu_id AND a2.pathlength > 0)
JOIN menu m2 ON (a2.menu_id = m2.id)
WHERE m1.active = 1
GROUP BY a2.menu_id;
結果:
+---------+-----------+-----------+
| menu_id | title | ancestors |
+---------+-----------+-----------+
| 2 | News | 1 |
| 3 | Foo | 2,1 |
| 4 | Bar | 3,2,1 |
| 5 | Downloads | 1 |
+---------+-----------+-----------+
所属していません StackOverflow