我有像这样的邻接列表模式结构
通过此查询
SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';
得到那样的结果
但我希望得到这样的结果,有任何选择吗
提前致谢
答案 0 :(得分:1)
不幸的是,使用您当前的设置很难计算某个类别的子类别数量。菜单的深度不仅受到您添加的LEFT JOIN
量的限制,而且也无法确定哪些类别直接链接到超过一个级别的类别。
此问题的一个出色解决方案是为菜单you can read more here使用nested set
结构。有关如何使用mysql here执行此操作的更多说明。
答案 1 :(得分:1)
你需要一个UNION,我建议删除各自级别的重复条目。此外,如果您打算像在Web应用程序中一样向用户显示,则无需包含“NULL”值
select L1.Category_ID,
L1.name,
"1" as HierarchyLevel,
count( L2.Category_ID ) as NextLevelCount
from Category L1
LEFT JOIN Category L2
on L1.Category_ID = L2.Parent
where L1.name = "ELECTRONICS"
group by L1.Category_ID
UNION
select L2.Category_ID,
L2.name,
"2" as HierarchyLevel,
count( L3.Category_ID ) as NextLevelCount
from Category L1
JOIN Category L2
on L1.Category_ID = L2.Parent
LEFT JOIN Category L3
on L2.Category_ID = L3.Parent
where L1.name = "ELECTRONICS"
group by L2.Category_ID
UNION
select L3.Category_ID,
L3.name,
"3" as HierarchyLevel,
count( L4.Category_ID ) as NextLevelCount
from Category L1
JOIN Category L2
on L1.Category_ID = L2.Parent
JOIN Category L3
on L2.Category_ID = L3.Parent
LEFT JOIN Category L4
on L3.Category_ID = L4.Parent
where L1.name = "ELECTRONICS"
group by L3.Category_ID
UNION
select L4.Category_ID,
L4.name,
"4" as HierarchyLevel,
1 as NextLevelCount
from Category L1
JOIN Category L2
on L1.Category_ID = L2.Parent
JOIN Category L3
on L2.Category_ID = L3.Parent
JOIN Category L4
on L3.Category_ID = L4.Parent
where L1.name = "ELECTRONICS"
这显然固定为4个级别,但会将它们合并为一个列表,但不会出现重复。我还提到了层次结构级别,仅供参考。为了获得每个级别的计数,你必须进行LEFT JOIN到下一级别,否则,你将错过你想要检索的级别的可能项目,但是其他项目应该保持为INNER JOIN。
如果你正在处理产品,我会认为如果没有经过4级深度后他们找不到东西,就会出现更大的问题:)
答案 2 :(得分:1)
作为一个兴趣点,因为它可能是太多的工作而且与你必须作为“答案”不同,我建议你研究“修改预先排序的树遍历”的概念。有一个很棒的explanation by Gijs Van Tulder。
它需要表上的其他字段来存储层次结构数据,并需要额外的代码来维护该结构,但它可以使关系数据库引擎中的树结构 更容易处理。
基本上,除了我们存储树的常用parent_id
之外,我们还存储了left
和right
值。正确填充后,只需选择node.left > parent.left
和node.right < parent.right
的所有节点,无论节点的深度如何,都可以轻松获得“节点的所有子节点”。
答案 3 :(得分:0)
您可以这样做:
SELECT name FROM category WHERE name = 'ELECTRONICS'
UNION
SELECT t2.name FROM t2 INNER JOIN category as t1 ON t2.parent = t1.category_id WHERE t1.name = 'ELECTRONICS'
UNION
SELECT t3.name FROM t3 INNER JOIN category as t1 ON t3.parent = t1.category_id WHERE t1.name = 'ELECTRONICS'
UNION
SELECT t4.name FROM t4 INNER JOIN category as t1 ON t4.parent = t1.category_id WHERE t1.name = 'ELECTRONICS'