【问题标题】:checking value in n-depth tree?检查n深度树中的值?
【发布时间】:2012-09-27 08:29:18
【问题描述】:

我有两个实体,postcategory,这是一个 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


【解决方案1】:

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

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

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

【讨论】:

  • 我们正在查看每个帖子平均 5 个类别,每个分支的深度大约为 5。总共大约 50 个类别,但是如果我们构建一个扁平树,我们不会有倒着走树?我们该怎么做?
  • @Hailwood:视情况而定。订单是否已经排序(孩子跟随他们的父母)?
  • 不排序,都是按照id排序的,所以按照创建顺序
【解决方案2】:

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

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

这同样适用于已排序的嵌套集,原理已在 this answer 中进行了概述,但是关于获取深度的算法不起作用,我建议使用能够删除隐藏项的 recursive iterator

此外,如果数据未排序,您可以根据the answer to Nested array. Third level is disappearing 中概述的所有行的(未排序)查询创建树结构。不需要递归,你得到一个可以轻松输出的结构,我也应该在另一个答案中涵盖&lt;ul&gt;/&lt;li&gt; html 样式输出。

【讨论】:

    猜你喜欢
    • 2021-11-22
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 2022-10-06
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    相关资源
    最近更新 更多