주어진 노드에서 SQL 계층에서 모든 잎 노드를 어떻게 선택할 수 있습니까?
문제
카테고리의 계층 구조를 모델링하는 데이터 세트가 있습니다. 루트 카테고리에는 최상위 범주 세트가 포함되어 있습니다. 각 최상위 범주에는 일련의 하위 범주가 포함되어 있습니다.
각 하위 범주에는 일련의 조직이 있습니다. 주어진 조직은 여러 하위 범주로 나타날 수 있습니다.
이 계층 구조의 잎 노드는 조직입니다. 조직은 잠재적으로 여러 하위 범주로 나타날 수 있습니다.
데이터는 3 개의 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을 사용 하여이 솔루션을 개발하고 있습니다.
시간과 제안에 감사드립니다.
해결책
계층 구조가 항상 정확히 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의 나무와 Smlies for Smarties의 Trees and Hierrarchies 계층 구조를 모델링하는 대안적인 방법. 어쨌든 그렇게하는 것이 좋은 생각 일 것입니다.
다른 팁
데이터 모델이 허용되는지 확실하지 않지만 단일 인덱스 열과 이진 트리를 사용 하여이 정보를 단일 '조직 트리'테이블에 쉽게 저장할 수 있습니다. 또한 카테고리, 하위 범주 또는 조직 레벨에서 검색하기 위해 수정없이 단일 쿼리를 사용하는 이점이 있습니다 (예 : X 하위 범주의 모든 결과를 제공 함).
도움이 되었기를 바랍니다.
아담.