【问题标题】:How can I select all leaf nodes in a SQL hierarchy under a given node?如何选择给定节点下 SQL 层次结构中的所有叶节点?
【发布时间】:2010-09-27 13:48:29
【问题描述】:

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

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

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

数据存储在三个 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 并执行选择以将所有组织映射到该类别。每个选择的结果都附加到一个数组中。只要组织出现在多个子类别中,此数组就会包含重复项。

我很想用一个查询替换这个杂项,该查询可以有效地选择一个不同组织的列表,给定一个层次结构中的一个类别的 id。

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

感谢您的宝贵时间和建议。

【问题讨论】:

    标签: php sql hierarchy


    【解决方案1】:

    假设您的层次结构总是正好 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 以了解对层次结构进行建模的替代方法。无论如何,这样做可能是个好主意。

    【讨论】:

      【解决方案2】:

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

      希望这会有所帮助。

      亚当。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-29
        • 1970-01-01
        • 1970-01-01
        • 2012-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多