对于一个简单的,可能是次优的,可扩展的解决方案,我建议使用您将拥有的最大级别对其进行硬编码:
仅限2个级别:
SELECT p2.name as `Parent name`, p1.*
FROM categories p1
LEFT JOIN categories p2 on p1.categories_id = p2.id
你真的在问排序,所以我建议你生成一个类似“路径”的字符串:
(请参阅下面的查询示例输出)
SELECT Concat(If(isnull(p2.name),"",Concat("/",p2.name)),"/",p1.name) as `generated path`, p2.name as `Parent name`, p1.*
FROM categories p1
LEFT JOIN categories p2 on p1.parent_id = p2.id
order by `generated path`
对于3个级别,虽然你的数据还没有这个 – 路径被省略,因为它会变得丑陋:)
SELECT p3.name as `Grandparent name`, p2.name as `Parent name`, p1.*
FROM categories p1
LEFT JOIN categories p2 on p1.categories_id = p2.id
LEFT JOIN categories p3 on p2.categories_id = p3.id
一个更全面的解决方案,用于快速选择任何级别的特定类别中的所有项目,这需要对所有写入进行一些工作,正在实施‘right’ and ‘left’ numbering concept.但是,对此的进一步讨论几乎肯定超出了您所要求的范围.然而,这是我的经验中唯一一个很好的方法,使这种自引用表非常有用,如果它会变大(可能在1000行3到10级之后).
附录:第二个查询的示例输出:
generated path Parent name id name parent_id
----------------------------------------------------------------------------
/apple 1 apple 0
/apple/lisa apple 5 lisa 1
/apple/mac apple 2 mac 1
/atari 3 atari 0
/atari/st atari 4 st 3