¿Cómo puedo seleccionar todos los nodos hoja en una jerarquía de SQL bajo un nodo dado?

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

  •  22-08-2019
  •  | 
  •  

Pregunta

Tengo un conjunto de datos que modela una jerarquía de categorías. Una categoría raíz contiene un conjunto de categorías de nivel superior. Cada categoría de nivel superior contiene un conjunto de sub-categorías.

Cada categoría sub tiene un conjunto de organizaciones. Una organización determinada puede aparecer en varias subcategorías.

Los nodos hoja de esta jerarquía son organizaciones. Una organización potencialmente puede aparecer en varias subcategorías.

Los datos se almacenan en tres tablas 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

Me gustaría ser capaz de seleccionar una lista de todas las organizaciones únicas en una categoría dada o subcategoría.

La forma en que estoy haciendo ahora mismo implica en primer lugar averiguar que se han solicitado subcategorías y luego bucle a través de cada uno sub_category en el código y realizar una selección para obtener todas las organizaciones asignadas a esa categoría. Los resultados de cada seleccione se añaden a una matriz. Esta matriz contiene duplicados cada vez que una organización aparece en múltiples subcategorías.

Me encantaría sustituir este kludge con una consulta que se pueden seleccionar de manera eficiente una lista de organizaciones distintas dado un identificador de una de las categorías en la jerarquía.

Estoy devloping esta solución usando PHP y MySQL.

Gracias por su tiempo y sugerencias.

¿Fue útil?

Solución

Si se asume que la jerarquía es siempre exactamente 3 niveles de profundidad:

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

Puede modificar que en un nivel que le permite pasar una sub categoría ID. Si usted no sabe en el momento si usted tiene o no un identificador de categoría o una subcategoría Identificación entonces usted puede hacer lo siguiente:

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

Si su jerarquía puede tener un número desconocido de niveles (o piensa que podría en el futuro) y luego salir noreferrer árboles de Joe Celko y jerarquías en SQL para Smarties formas alternativas para modelar una jerarquía. Es probablemente una buena idea hacer eso de todos modos.

Otros consejos

No está seguro de si su modelo de datos lo permite, pero se puede utilizar una columna de índice individual y un árbol binario para almacenar fácilmente esta información en una sola tabla 'OrganizationTree'. También tiene la ventaja de utilizar una sola consulta sin modificaciones para buscar en los planos categoría, subcategoría, o de la organización (Por ejemplo dame todos los resultados de X subcategoría)

Espero que esto ayude.

Adam.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top