MySQL - 如何访问 table 级别 2 中的所有节点
MySQL - How to access all nodes in level 2 in table
我正在为具有嵌套类别的 e-commerce 网站创建数据库,并且我正在使用 修改后的预序遍历算法 。我的问题是如何访问级别 2 中的所有节点,即 Articles、Portfolio、Contact
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;
编辑(发生了什么):
为了利用 nested_category
table 的 lft
和 rgt
列,我们应该 select 两次 table .
SELECT *
FROM nested_category AS node, nested_category AS parent
如果您检查此查询,您会发现对于 nested_category
中的每一行,我们再次 select 所有行。所以我们现在想要的是从第一个 table(我们称为 AS node
的行)中删除它们不是 parent
的 child 的所有行。这就是我们使用 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;
所以现在我们拥有所有 child 及其 parents + 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 |
+-------------+----------------------+-----+-----+-------------+----------------------+------+------+
下一步 - 获取深度计数。为了做到这一点,我们必须按每个 child 进行分组(该示例使用 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 |
+-------------+----------------------+-----+-----+-------+
我希望现在更清楚了。如果我犯了一些错误,再次为我糟糕的英语感到抱歉。
我正在为具有嵌套类别的 e-commerce 网站创建数据库,并且我正在使用 修改后的预序遍历算法 。我的问题是如何访问级别 2 中的所有节点,即 Articles、Portfolio、Contact
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;
编辑(发生了什么):
为了利用 nested_category
table 的 lft
和 rgt
列,我们应该 select 两次 table .
SELECT *
FROM nested_category AS node, nested_category AS parent
如果您检查此查询,您会发现对于 nested_category
中的每一行,我们再次 select 所有行。所以我们现在想要的是从第一个 table(我们称为 AS node
的行)中删除它们不是 parent
的 child 的所有行。这就是我们使用 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;
所以现在我们拥有所有 child 及其 parents + 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 |
+-------------+----------------------+-----+-----+-------------+----------------------+------+------+
下一步 - 获取深度计数。为了做到这一点,我们必须按每个 child 进行分组(该示例使用 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 |
+-------------+----------------------+-----+-----+-------+
我希望现在更清楚了。如果我犯了一些错误,再次为我糟糕的英语感到抱歉。