У меня есть эта таблица:
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>
Разница в том, что у меня много деревьев в одной таблице. Каждая строка имеет внешний ключ, представляющий ее родительский элемент и его главный родитель: 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, чтобы я мог сгенерировать правильное дерево.
Кроме того, после получения дерева, есть ли способ упорядочить каждый узел по имени?
Как вы можете видеть, мне нужно также заказать root_id, чтобы я мог сгенерировать правильное дерево.
При построении модели вложенного дерева никогда не делайте дубликатов на rgt
и rgt
. Фактически, вы должны объявить их уникальными.
В вашей модели данных наборы для категорий 1
и 8
перекрываются. Скажем, от 1
до 14
используются как для пунктов 1
и 8
.
Замените их следующими значениями:
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
должны иметь больше rgt
и rgt
:
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);
Вложенное дерево может иметь только один неявный порядок.
Существует также способ запросить список смежности в MySQL
:
, однако вам нужно создать дополнительный уникальный столбец для заказа, если вы хотите заказать что-либо еще, кроме id
.
Вы также можете прочитать эту статью:
который показывает, как лучше хранить и запрашивать вложенные наборы.
Я понял.
Все, что вам нужно сделать, это установить root_id на верхних родителей, чтобы вы могли правильно выполнить ORDER BY.
С запросом ниже я могу разделить деревья и отобразить только дерево, над которым я работаю:
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