我有一组数据来模拟类别的层次结构。根类别包含一组顶级类别。每个顶级类别都包含一组子类别。
每个子类别都有一组组织。给定组织可以出现在多个子类别中。
此层次结构的叶节点是组织。组织可能会出现在多个子类别中。
数据存储在三个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开发这个解决方案。
感谢您的时间和建议。
答案 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子类别的所有结果)
希望这有帮助。
亚当。