【发布时间】:2012-09-27 08:29:18
【问题描述】:
我有两个实体,post 和 category,这是一个 1:n 关系。
我有一个包含两列的参考表,post_id,category_id
categories 表有一个id 列、一个status 列和一个parent_id 列
如果一个类别是另一个类别(n 深度)的子类别,那么它的 parent_id 不为空。
如果类别在线,则状态为 1,否则为 0。
我需要做的是找出帖子是否可见。
这需要:
加入帖子的 Foreach 类别将其树向上跟踪到根节点(直到类别具有 parent_id == null),如果其中任何类别具有 status 0,则该路径被视为脱机。
如果任何路径在线,则认为帖子可见,否则将其隐藏。
我能想到的唯一方法(作为半伪代码)是:
function visible(category_ids){
categories = //select * from categories where id in(category_ids)
online = false
foreach(categories as category){
if(category.status == 0)
continue;
children = //select id from categories where parent_id = category.id
if(children)
online = visible(children)
}
return online
}
categories = //select c.id from categories c join posts_categories pc on pc.category_id = c.id where pc.post_id = post.id
post.online = visible(categories)
但这可能最终会成为很多 sql 查询,有没有更好的方法?
【问题讨论】:
-
更好的方法称为嵌套集。您也可以预先订购此产品,这样您就可以通过一个查询来解决输出问题。见Getting nested set model into a <ul> but hiding “closed” subtrees。
-
这里不能使用嵌套集,因为数据通常会在树的中间添加/删除
-
您添加和删除的频率是否高于显示频率?这个列表有多大?
-
嗯,这是一个博客,所以半定期更新。它实际上是一个 cms 的通用模块,所以我无法给出比这更清晰的答案。
-
好吧,我们只是说嵌套集不是一个选项,因为您不想更改数据结构。实际上,我会说嵌套集模型对此非常有用,您将来可能要重新考虑这一点。无论如何,在该链接答案中完成的部分优化也适用于您的结构的排序数据集。但是您仍然需要解决排序问题。我添加了这个作为答案。
标签: php mysql adjacency-list