10

我正在用 PHP / MySQL / Javascript 编程。我有一个我们想要在子/父关系中链接的部分列表,对层数没有限制。

当我从零件列表中挑选以将孩子添加到父母时,我会限制零件列表以排除父母本身以及已经是该父母的孩子的任何零件。

我发现我还想排除父母的祖父母,否则我们会得到乱伦关系,当我显示零件树时会产生无限循环。

不仅如此,我不能让孩子成为父母的曾祖父母或曾曾祖父母等

这是我目前使用的 SQL 语句,我认为也可以通过使用来改进,LEFT JOIN但我目前对 SQL 不够熟练。

SELECT * 
FROM sch_part_general 
WHERE (sch_part_general.part_id <> $parentId) 
AND (sch_part_general.part_id NOT IN 
  (SELECT part_id FROM sch_part_mapping WHERE parent_id = $parentId)
)

sch_part_general 是一个包含所有部分的多列表,以 part_id 作为主键。sch_part_mapping 是一个带有part_id (child) || 的两列映射表 parent_id(父母)。

有人可以通过 SQL 查询为我指明正确的方向吗?我不热衷于使用 while 循环来创建 SQL 语句,因为我认为这将非常低效,但这是我认为迄今为止唯一可行的方法。

4

3 回答 3

6

MySQL对分层查询没有太多(如果有的话)支持。如果您想坚持所谓的Adjacency List Model,您所能做的就是JOIN为您想要包含的每个级别添加一个。不用说,这不能很好地扩展。

另一方面,如果您可以更改数据库架构,我建议您实施Nested Set Model.

Mike Hillyer 的博客Nested Set Model中提供了一个很好的解释

邻接表模型的局限性

在纯 SQL 中使用邻接表模型可能很困难。在能够看到一个类别的完整路径之前,我们必须知道它所在的级别。

嵌套集模型

SQL 中嵌套集的概念已经存在了十多年,并且在书籍和 Internet 上提供了很多附加信息。在我看来,关于管理分层信息的最全面的信息来源是一本书,名为 Joe Celko 为 Smarties 编写的 SQL 中的树和层次结构,由高级 SQL 领域的一位非常受人尊敬的作者 Joe Celko 撰写。

于 2012-07-25T14:55:31.597 回答
1

如果你不能改变模式,那么就像 Lieven 的回答所暗示的那样,没有逃避循环的可能。

如果您可以更改架构,那么对于您的情况,以下内容可能就足够了:向 sch_part_mapping 添加一个新列,我们将其称为“hierarchy_id”。它是一个在您第一次开始一个全新的层次结构时构造为唯一 int 的值(具有任何层次结构中的第一个 Grand Grand Grandest Grandmost 父级 - 但是它用英语表示)并插入到属于单个层次结构的所有行中 否不管在什么水平。

然后,很容易跳过在同一层次结构中找到的父母和祖父母:然后您可以在上面的 sql 中添加:

SELECT * 
FROM sch_part_general 
WHERE (sch_part_general.part_id <> $parentId) 
AND (sch_part_general.part_id NOT IN 
  (SELECT part_id FROM sch_part_mapping WHERE parent_id = $parentId)

//addition here 
and not exists (select * from sch_part_mapping where hierarchy_id= ? and parent_id = sch_part_general.part_id)

)

问号应替换为您需要计算的相关层次结构 ID。

编辑:我错过了您有一个特定父 ID 的变量,因此可以在同一个查询中计算 hierarchy_id:

SELECT * 
    FROM sch_part_general 
    WHERE (sch_part_general.part_id <> $parentId) 
    AND (sch_part_general.part_id NOT IN 
      (SELECT part_id FROM sch_part_mapping WHERE parent_id = $parentId)

    //addition here 
    and not exists (select * from sch_part_mapping where hierarchy_id= (select hierarchy_id from sch_part_mapping where parent_id = $parentId limit 1) and parent_id = sch_part_general.part_id)


)
于 2012-07-25T16:17:36.973 回答
0

使用 MySql/MariaDB,您可以使用 Open Query Graph 引擎 ( http://openquery.com/graph/doc ),它是一个 mysql 插件,可让您创建一个特殊的表来放置关系,基本上是 parentId 和 childId。

神奇的是,您使用特殊的列锁存器查询此表,具体取决于查询中传递的值,它将告诉 OQGRAPH 引擎执行哪个命令。有关详细信息,请参阅文档。

它不仅处理树(递归 1-n 关系),而且处理带有权重的图形数据结构(递归 nm 关系)(例如,您想存储公司所有权,公司可以有多个子公司,也可以有多个股东)。

于 2013-04-04T12:02:02.707 回答