Como posso selecionar todos os nós de folha em uma hierarquia SQL sob um determinado nó?

StackOverflow https://stackoverflow.com/questions/378608

  •  22-08-2019
  •  | 
  •  

Pergunta

Eu tenho um conjunto de dados que modela uma hierarquia de categorias. A categoria raiz contém um conjunto de categorias de nível superior. Cada categoria de nível superior contém um conjunto de sub-categorias.

Cada categoria sub tem um conjunto de organizações. A organização dada pode aparecer em vários sub-categorias.

Os nós de folha dessa hierarquia são organizações. Uma organização pode potencialmente aparecer em vários sub-categorias.

Os dados são armazenados em três tabelas 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

Eu gostaria de ser capaz de selecionar uma lista de todas as organizações únicas sob uma determinada categoria ou sub-categoria.

A maneira que eu estou fazendo isso agora envolve primeiro descobrir qual subcategorias foram solicitadas e, em seguida, um loop através de cada sub_category no código e realizar uma seleção para obter todas as organizações mapeadas a essa categoria. Os resultados de cada seleccione são anexados a uma matriz. Esta matriz contém duplicatas, sempre que uma organização aparece em várias categorias sub.

Eu adoraria substituir este kludge com uma consulta que pode eficientemente selecionar uma lista de organizações distintas dado um id de uma das categorias na hierarquia.

Estou devloping esta solução usando PHP e MySQL.

Obrigado por seu tempo e sugestões.

Foi útil?

Solução

Assumindo que a hierarquia é sempre exatamente 3 níveis de profundidade:

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

Você pode modificar que em um nível que lhe permite passar um ID de sub categoria. Se você não sabe no momento se você tem ou não um ID de categoria ou uma categoria sub id, então você pode fazer o seguinte:

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

Se a sua hierarquia pode ter um número desconhecido de níveis (ou você acha que pode no futuro), então confira Árvores e hierarquias de Joe Celko em SQL para Smarties para formas alternativas para modelar uma hierarquia. É provavelmente uma boa idéia para fazer isso de qualquer maneira.

Outras dicas

Não tenho certeza se o seu modelo de dados vai permitir isso, mas você pode usar uma única coluna de índice e uma árvore binária para armazenar facilmente esta informação em uma única tabela 'OrganizationTree'. Também tem a vantagem de utilizar uma única consulta sem modificações para procurar nos níveis categoria, subcategoria ou organização (por exemplo, dá-me todos os resultados do X subcategoria)

Espero que isso ajude.

Adam.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top