我有一个MySQL表,其作用类似于嵌套集,以便包含类别层次结构。表模式如下所示:
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(200) NOT NULL,
`parent_id` int(11) default NULL,
`lft` int(11) default NULL,
`rgt` int(11) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_categories_on_parent_id_and_name` (`parent_id`,`name`)
)
lft
和rgt
定义节点的左右边界(嵌套集的工作方式是每个节点的id都在其父节点内),parent_id
指定父节点。唯一索引允许存在多个具有相同名称的类别,只要它们没有相同的父级。
我试图找出一种基于层次结构在集合中查找特定节点的正确方法。例如,如果我查找foo / bar / baz,我想检索名为baz的节点,其父节点名为bar,其父节点名为foo。显然,我不能只按名称搜索,因为可能有多个具有相同名称的类别。
我能想到这样做的方法是找到最顶层的类别,然后找到具有给定名称的每个后续类别,其父ID是先前找到的类别,但这对我来说似乎不是很有效。有没有更好的方法来搜索嵌套集?
答案 0 :(得分:1)
我不相信使用嵌套集有一个非常干净和有效的方法。在非规范化列中存储节点祖先的列表可以有效地提供这一点,但我不建议实现它。
虽然有一个ok'ish方法,它是1个查询,并且可以方便地点击你已经拥有的索引。您正在为目标节点的每个深度级别查看一个连接。
对于你的例子foo-bar-baz
select c3.*
from categories c1
inner join categories c2 on c2.parent_id = c1.id AND c2.name = 'bar'
inner join categories c3 on c3.parent_id = c2.id AND c2.name = 'baz'
where c1.name = 'foo'
这不是最好的,但它可能是你最好的选择,除非你想要存储一堆非规范化信息。在代码中生成SQL也相当简单。
答案 1 :(得分:1)
TopVar = 'foo'
MidVar = 'bar'
BotVar = 'baz'
SELECT D0.*
FROM categories D0, categories D1, categories D2
WHERE D0.name = :BotVar
AND D0.lft > D1.lft
AND D0.rgt < D1.rgt
AND D1.name = :MidVar
AND D1.lft > D2.lft
AND D1.rgt < D2.rgt
AND D2.name = :TopVar;
-Al。
答案 2 :(得分:0)
我之前在一个交给我的php项目中看过这个,呃,这很糟糕.. 如果可以,将其分成至少2个表;至少有1个类别和1个项目,所以你可以加入..无论哪种方式你都需要做多个查询我害怕