Я создаю базу данных для веб-сайта электронной коммерции, у которых есть вложенные категории, и я использую измененный предварительный переход algo. Мой вопрос, как я могу получить доступ ко всем узлам уровня 2 т.е. Статьи, Портфолио, КонтактMySQL - Как получить доступ ко всем узлам уровня 2 в таблице
ответ
The article прямо не говорит вам, как получить все узлы от одного уровня. Но если вы внимательно прочитаете это, он расскажет вам, как делать больше -> получить количество глубин каждой категории. Тогда все, что вам нужно сделать, это отфильтровать эту глубину.
SELECT node.name, (COUNT(parent.name) - 1) AS depth
FROM nested_category AS node, nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
HAVING depth = 1
ORDER BY node.lft;
EDIT (что происходит):
Для того, чтобы использовать lft
и rgt
столбцов nested_category
таблицы следует выбрать таблицу дважды.
SELECT *
FROM nested_category AS node, nested_category AS parent
если вы проверяете этот запрос, вы увидите, что для каждой строки в nested_category
мы выбираем все строки снова. Итак, теперь мы хотим удалить все строки из первой таблицы (тот, который мы назвали AS node
), где они не являются дочерними из их parent
. Именно поэтому мы фильтруем с WHERE node.lft BETWEEN parent.lft AND parent.rgt
Я хочу отметить, что этот запрос:
SELECT *
FROM nested_category AS node, nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
ORDER BY node.lft;
равно
SELECT *
FROM nested_category AS node
LEFT JOIN nested_category AS parent ON (node.lft BETWEEN parent.lft AND parent.rgt)
ORDER BY node.lft;
Так что теперь у нас есть все ребенка с родителями + 1 (из-за пути процеживаем, каждый child
принадлежат к себе)
+-------------+----------------------+-----+-----+-------------+----------------------+------+------+
| category_id | name | lft | rgt | category_id | name | lft | rgt |
+-------------+----------------------+-----+-----+-------------+----------------------+------+------+
| 1 | ELECTRONICS | 1 | 20 | 1 | ELECTRONICS | 1 | 20 |
| 2 | TELEVISIONS | 2 | 9 | 1 | ELECTRONICS | 1 | 20 |
| 2 | TELEVISIONS | 2 | 9 | 2 | TELEVISIONS | 2 | 9 |
| 3 | TUBE | 3 | 4 | 1 | ELECTRONICS | 1 | 20 |
| 3 | TUBE | 3 | 4 | 3 | TUBE | 3 | 4 |
| 3 | TUBE | 3 | 4 | 2 | TELEVISIONS | 2 | 9 |
| 4 | LCD | 5 | 6 | 2 | TELEVISIONS | 2 | 9 |
| 4 | LCD | 5 | 6 | 1 | ELECTRONICS | 1 | 20 |
| 4 | LCD | 5 | 6 | 4 | LCD | 5 | 6 |
| 5 | PLASMA | 7 | 8 | 1 | ELECTRONICS | 1 | 20 |
| 5 | PLASMA | 7 | 8 | 5 | PLASMA | 7 | 8 |
| 5 | PLASMA | 7 | 8 | 2 | TELEVISIONS | 2 | 9 |
| 6 | PORTABLE ELECTRONICS | 10 | 19 | 6 | PORTABLE ELECTRONICS | 10 | 19 |
| 6 | PORTABLE ELECTRONICS | 10 | 19 | 1 | ELECTRONICS | 1 | 20 |
| 7 | MP3 PLAYERS | 11 | 14 | 7 | MP3 PLAYERS | 11 | 14 |
| 7 | MP3 PLAYERS | 11 | 14 | 1 | ELECTRONICS | 1 | 20 |
| 7 | MP3 PLAYERS | 11 | 14 | 6 | PORTABLE ELECTRONICS | 10 | 19 |
| 8 | FLASH | 12 | 13 | 1 | ELECTRONICS | 1 | 20 |
| 8 | FLASH | 12 | 13 | 8 | FLASH | 12 | 13 |
| 8 | FLASH | 12 | 13 | 6 | PORTABLE ELECTRONICS | 10 | 19 |
| 8 | FLASH | 12 | 13 | 7 | MP3 PLAYERS | 11 | 14 |
| 9 | CD PLAYERS | 15 | 16 | 1 | ELECTRONICS | 1 | 20 |
| 9 | CD PLAYERS | 15 | 16 | 9 | CD PLAYERS | 15 | 16 |
| 9 | CD PLAYERS | 15 | 16 | 6 | PORTABLE ELECTRONICS | 10 | 19 |
| 10 | 2 WAY RADIOS | 17 | 18 | 1 | ELECTRONICS | 1 | 20 |
| 10 | 2 WAY RADIOS | 17 | 18 | 10 | 2 WAY RADIOS | 17 | 18 |
| 10 | 2 WAY RADIOS | 17 | 18 | 6 | PORTABLE ELECTRONICS | 10 | 19 |
+-------------+----------------------+-----+-----+-------------+----------------------+------+------+
Следующий шаг - введите значение глубины. Для того, чтобы сделать это, мы должны группе каждого ребенка (в данном примере используется GROUP BY node.name
, но он также может быть сделано на node.category_id
и подсчитать количество parents
- 1 для каждой группы (COUNT(parent.name) - 1) AS depth
(ее также отлично использовать parent.category_id
вместо)
Так делают
SELECT node.*, (COUNT(parent.category_id) - 1) AS depth
FROM nested_category AS node
LEFT JOIN nested_category AS parent ON (node.lft BETWEEN parent.lft AND parent.rgt)
GROUP BY node.category_id
ORDER BY node.lft;
мы получаем это
+-------------+----------------------+-----+-----+-------+
| category_id | name | lft | rgt | depth |
+-------------+----------------------+-----+-----+-------+
| 1 | ELECTRONICS | 1 | 20 | 0 |
| 2 | TELEVISIONS | 2 | 9 | 1 |
| 3 | TUBE | 3 | 4 | 2 |
| 4 | LCD | 5 | 6 | 2 |
| 5 | PLASMA | 7 | 8 | 2 |
| 6 | PORTABLE ELECTRONICS | 10 | 19 | 1 |
| 7 | MP3 PLAYERS | 11 | 14 | 2 |
| 8 | FLASH | 12 | 13 | 3 |
| 9 | CD PLAYERS | 15 | 16 | 2 |
| 10 | 2 WAY RADIOS | 17 | 18 | 2 |
+-------------+----------------------+-----+-----+-------+
И теперь последний шаг, чтобы сказать, что мы хотим, только эти записи, которые имеют глубину = 1 (HAVING depth = 1
. HAVING
используется здесь, потому что он применяется после агрегатов (и поэтому он может фильтровать на агрегатах))
SELECT node.*, (COUNT(parent.category_id) - 1) AS depth
FROM nested_category AS node
LEFT JOIN nested_category AS parent ON (node.lft BETWEEN parent.lft AND parent.rgt)
GROUP BY node.category_id
HAVING depth = 1
ORDER BY node.lft;
+-------------+----------------------+-----+-----+-------+
| category_id | name | lft | rgt | depth |
+-------------+----------------------+-----+-----+-------+
| 2 | TELEVISIONS | 2 | 9 | 1 |
| 6 | PORTABLE ELECTRONICS | 10 | 19 | 1 |
+-------------+----------------------+-----+-----+-------+
Я надеюсь, что его более ясно. Снова извините за мой плохой английский, если я допустил некоторые ошибки.
Что это за номера? Почему этот заказ? –
@MihaiIorga http: // imrannazar.com/Modified-Preorder-Tree-Traversal pls см. ссылку – Cody
С моей точки зрения, [это изображение] (http://i.imgur.com/FP8pXTZ.png) следует объяснить, как я рассматриваю структуру дерева категорий. Гораздо проще выбирать и получать узлы. Это будет просто 'SELECT * FROM категорий, где parent_id = 1' –