如何在给定节点下的SQL层次结构中选择所有叶节点?

时间:2008-12-18 17:41:31

标签: php sql hierarchy

我有一组数据来模拟类别的层次结构。根类别包含一组顶级类别。每个顶级类别都包含一组子类别。

每个子类别都有一组组织。给定组织可以出现在多个子类别中。

此层次结构的叶节点是组织。组织可能会出现在多个子类别中。

数据存储在三个SQL表中:

organizations
organization_id organization_name
1               Org A
2               Org B
3               Org C
4               Org D
5               Org E
6               Org F

categories
category_id parent_id category_name
0           NULL      Top Level Category
1           0         First Category
2           0         Second Category
3           1         Sub Category A
4           1         Sub Category B
5           1         Sub Category C
6           2         Sub Category D

organizations_categories -- Maps organizations to sub_categories
organization_id category_id
1               3
2               3
2               6
3               4
4               4
5               4
6               5
6               4
7               6
8               6

我希望能够在给定类别或子类别下选择所有独特组织的列表。

我现在正在做的方式包括首先确定已经请求了哪些子类别,然后在代码中循环遍历每个sub_category并执行选择以使所有组织映射到该类别。每个选择的结果都附加到一个数组。只要组织出现在多个子类别中,此数组就包含重复项。

我希望用一个查询来替换这个kludge,该查询可以有效地选择一个不同组织的列表,给出ID在层次结构中的一个类别。

我正在使用PHP和MySQL开发这个解决方案。

感谢您的时间和建议。

2 个答案:

答案 0 :(得分:4)

假设您的层次结构总是精确到3级:

SELECT DISTINCT
     O.organization_id,
     O.organization_name
FROM
     Categories CAT
INNER JOIN Categories SUB ON
     SUB.parent_id = CAT.category_id
INNER JOIN Category_Organizations CO ON
     CO.category_id = SUB.category_id
INNER JOIN Organizations O ON
     O.organization_id = CO.organization_id
WHERE
     CAT.category_id = @category_id

您可以将其修改为一个级别,以允许您传递子类别ID。如果您当时不知道您是否有类别ID或子类别ID,那么您可以执行以下操作:

SELECT DISTINCT
     O.organization_id,
     O.organization_name
FROM
     Categories CAT
LEFT OUTER JOIN Categories SUB ON
     SUB.parent_id = CAT.category_id
INNER JOIN Category_Organizations CO ON
     CO.category_id IN (CAT.category_id, SUB.category_id)
INNER JOIN Organizations O ON
     O.organization_id = CO.organization_id
WHERE
     CAT.category_id = @category_id

如果您的层次结构可能具有未知数量的级别(或者您认为它可能在未来),那么请查看Joe Celko's Trees and Hierarchies in SQL for Smarties以了解对层次结构建模的其他方法。无论如何,这可能是个好主意。

答案 1 :(得分:0)

不确定您的数据模型是否允许它,但您可以使用单个索引列和二叉树轻松地将此信息存储在单个“OrganizationTree”表中。您还可以使用单个查询而无需修改来搜索类别,子类别或组织级别(例如,给我X子类别的所有结果)

希望这有帮助。

亚当。