1

我有两个实体,postcategory是一个1:n关系。

我有一个包含两列的参考表post_idcategory_id

categories有一id列,一status列,一parent_id

如果一个类别是另一个类别(n 深度)的子类别,则它parent_id不为空。

如果一个类别在线,则其状态为 1,否则为 0。

我需要做的是找出帖子是否可见。

这需要:

Foreach 类别加入到帖子跟踪它的树到根节点(直到类别具有parent_id== null),如果这些类别中的任何一个具有status0 则该路径被认为是离线的。

如果任何路径在线,则认为该帖子可见,否则将其隐藏。

我能想到的唯一方法(作为半伪代码)是:

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 查询,有没有更好的方法?

4

2 回答 2

0

经典的数据库与内存的权衡。你正在做的是建造一棵树,里面有叶子。要构建树,您需要递归循环叶子。来自数据库有两种情况:

  1. 使用对每个叶子的查询构建递归树。您在内存中拥有 1 棵树。这就是你正在做的事情。
  2. 从数据库中获取平面结构,并在内存中递归构建树。你在记忆中拥有一棵扁平的树和真正的树。那是你的替代方式。

什么更好取决于很多事情:您的硬件(磁盘访问与内存),树的大小等等。

于 2012-10-06T10:21:55.017 回答
0

如果嵌套集不是一个选项,我知道以下内容:

  • 如果对数据进行排序,以便父项的子项始终跟随在其父项之后,则可以通过跳过输出中的隐藏节点来对所有数据进行一次数据库查询来解决此问题。

这同样适用于排序的嵌套集,原理已在此答案中概述,但是有关获取深度的算法不起作用,我建议使用能够删除隐藏项的递归迭代器。

此外,如果数据未排序,您可以从所有行的(未排序)查询中创建一个树结构,如嵌套数组的答案中所述。第三层正在消失。不需要递归,并且您可以获得一个可以轻松输出的结构,我也应该<ul>/<li>在另一个答案中涵盖 html 样式输出。

于 2012-10-06T10:33:50.913 回答