7

私はこのテーブルを持っています:

CREATE TABLE `categories` (
  `id` int(11) NOT NULL auto_increment,
  `category_id` int(11) default NULL,
  `root_id` int(11) default NULL,
  `name` varchar(100) collate utf8_unicode_ci NOT NULL,
  `lft` int(11) NOT NULL,
  `rht` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `category_id` (`category_id`),
  KEY `lft` (`lft`,`rht`),
  KEY `root_id` (`root_id`)
) 

この質問に基づいて: 変更された事前注文ツリー トラバーサル モデル (ネストされたセット) を <ul> に取得する

違いは、1 つのテーブルに多くのツリーがあることです。各行には、その親とその最上位の親を表す外部キー (category_id と root_id) があります。また、この例に基づいて lft フィールドと rht フィールドがあります: http://articles.sitepoint.com/article/hierarchical-data-database/2

この行に基づいて:

INSERT INTO `categories` VALUES(1, NULL, NULL, 'Fruits', 1, 14);
INSERT INTO `categories` VALUES(2, 1, 1, 'Apple', 2, 3);
INSERT INTO `categories` VALUES(3, 1, 1, 'Orange', 4, 9);
INSERT INTO `categories` VALUES(4, 3, 1, 'Orange Type 1', 5, 6);
INSERT INTO `categories` VALUES(5, 3, 1, 'Orange Type 2', 7, 8);
INSERT INTO `categories` VALUES(6, 1, 1, 'Pear', 10, 11);
INSERT INTO `categories` VALUES(7, 1, 1, 'Banana', 12, 13);
INSERT INTO `categories` VALUES(8, NULL, NULL, 'Eletronics', 1, 14);
INSERT INTO `categories` VALUES(9, 8, 8, 'Cell Phones', 2, 3);
INSERT INTO `categories` VALUES(10, 8, 8, 'Computers', 4, 9);
INSERT INTO `categories` VALUES(11, 10, 8, 'PC', 5, 6);
INSERT INTO `categories` VALUES(12, 10, 8, 'MAC', 7, 8);
INSERT INTO `categories` VALUES(13, 8, 8, 'Printers', 10, 11);
INSERT INTO `categories` VALUES(14, 8, 8, 'Cameras', 12, 13);

このツリーを表す順序付きリストを作成するにはどうすればよいですか?

次のSQLを使用します。

SELECT c. * , (COUNT( p.id ) -1) AS depth
FROM `categorias` AS p
CROSS JOIN categories AS c
WHERE (
c.lft
BETWEEN p.lft
AND p.rht
)
GROUP BY c.id
ORDER BY c.lft;

私はこの結果を得ました:

代替テキスト

ご覧のとおり、正しいツリーを生成できるように、root_id で並べ替える必要もあります。

また、ツリーを取得した後、各ノードを名前で並べ替える方法はありますか?

4

2 に答える 2

2

ご覧のとおり、正しいツリーを生成できるように、root_id で並べ替える必要もあります。

ネストされたツリー モデルを構築するときは、 と で重複を作成しないlftrgtください。実際、それらは一意であると宣言する必要があります。

あなたのデータモデルでは、カテゴリ18重複のセットがあります。たとえば、1toは itemと14の両方に使用されます。18

それらを次の値に置き換えます。

INSERT INTO `categories` VALUES(1, NULL, NULL, 'Fruits', 1, 14);
INSERT INTO `categories` VALUES(2, 1, 1, 'Apple', 2, 3);
INSERT INTO `categories` VALUES(3, 1, 1, 'Orange', 4, 9);
INSERT INTO `categories` VALUES(4, 3, 1, 'Orange Type 1', 5, 6);
INSERT INTO `categories` VALUES(5, 3, 1, 'Orange Type 2', 7, 8);
INSERT INTO `categories` VALUES(6, 1, 1, 'Pear', 10, 11);
INSERT INTO `categories` VALUES(7, 1, 1, 'Banana', 12, 13);
INSERT INTO `categories` VALUES(8, NULL, NULL, 'Eletronics', 15, 29);
INSERT INTO `categories` VALUES(9, 8, 8, 'Cell Phones', 16, 17);
INSERT INTO `categories` VALUES(10, 8, 8, 'Computers', 19, 24);
INSERT INTO `categories` VALUES(11, 10, 8, 'PC', 20, 21);
INSERT INTO `categories` VALUES(12, 10, 8, 'MAC', 22, 23);
INSERT INTO `categories` VALUES(13, 8, 8, 'Printers', 25, 26);
INSERT INTO `categories` VALUES(14, 8, 8, 'Cameras', 27, 28);

で注文する必要はありませんroot_id

また、ツリーを取得した後、各ノードを名前で並べ替える方法はありますか?

最初から名前順にノードを挿入しない限り、簡単な方法ではありません。より大きな値を持つ兄弟は、より大きくとnameを持つ必要があります。lftrgt

INSERT INTO `categories` VALUES(1, NULL, NULL, 'Fruits', 1, 14);
INSERT INTO `categories` VALUES(2, 1, 1, 'Apple', 2, 3);
INSERT INTO `categories` VALUES(7, 1, 1, 'Banana', 4, 5);
INSERT INTO `categories` VALUES(3, 1, 1, 'Orange', 6, 11);
INSERT INTO `categories` VALUES(4, 3, 1, 'Orange Type 1', 7, 8);
INSERT INTO `categories` VALUES(5, 3, 1, 'Orange Type 2', 9, 10);
INSERT INTO `categories` VALUES(6, 1, 1, 'Pear', 12, 13);

ネストされたツリーは、暗黙的な順序を 1 つだけ持つことができます。

で隣接リストを照会する方法もありますMySQL

、ただし、以外で注文する場合は、追加の一意の注文列を作成する必要がありますid

次の記事もお読みください。

これは、ネストされたセットをより効率的に格納およびクエリする方法を示しています。

于 2010-09-03T20:40:19.340 に答える
0

わかった。

正しく注文できるように、root_idを上位の親にも設定するだけです。

以下のクエリを使用して、木を分離し、作業中の木のみを更新することができます。

SELECT c . * , count( p.id ) AS depth
FROM `categories` c
CROSS JOIN categories p
WHERE (
c.lft
BETWEEN p.lft
AND p.rht
)
AND c.root_id = p.root_id
GROUP BY c.id
ORDER BY c.root_id, c.lft
于 2010-09-06T00:11:28.027 に答える