Come posso selezionare tutti i nodi foglia di una gerarchia di SQL nell'ambito di un dato nodo?

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

  •  22-08-2019
  •  | 
  •  

Domanda

Ho una serie di dati che modelli una gerarchia di categorie. Una categoria radice contiene una serie di categorie di livello superiore. Ogni categoria di livello superiore contiene una serie di sotto-categorie.

Ogni categoria sub ha una serie di organizzazioni. Una data organizzazione può apparire in più categorie secondarie.

I nodi foglia di questa gerarchia sono organizzazioni. Un'organizzazione può potenzialmente comparire in più sotto-categorie.

I dati vengono memorizzati in tre tabelle 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

Mi piacerebbe essere in grado di selezionare un elenco di tutte le organizzazioni unici sotto una determinata categoria o sottocategoria.

Il modo in cui sto facendo proprio ora prevede prima capire quali categorie secondarie sono stati richiesti e poi loop attraverso ogni sub_category nel codice e l'esecuzione di una selezione per ottenere tutte le organizzazioni mappati a quella categoria. I risultati di ogni select vengono aggiunti a un array. Questo array contiene i duplicati ogni volta che un'organizzazione appare in più sotto categorie.

Mi piacerebbe sostituire questo ripiego con una query che può efficacemente selezionare un elenco di organizzazioni distinte dato un id di una delle categorie nella gerarchia.

Sto devloping questa soluzione utilizzando PHP e MySQL.

Grazie per il tuo tempo e suggerimenti.

È stato utile?

Soluzione

Supponendo che la gerarchia è sempre esattamente 3 livelli di profondità:

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

È possibile modificare che di un livello per consentire di passare una sotto categoria id. Se non si conosce al momento se non si dispone di un ID categoria o una sottocategoria id allora si può fare quanto segue:

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 la gerarchia può avere un numero imprecisato di livelli (o pensi che possa in futuro) quindi controllare noreferrer Alberi di Joe Celko e gerarchie in SQL per Smarties di modi alternativi per modellare una gerarchia. E 'probabilmente una buona idea di farlo comunque.

Altri suggerimenti

Non sono sicuro se il vostro modello di dati lo permette, ma è possibile utilizzare una colonna di indice singolo e un albero binario per memorizzare facilmente queste informazioni in un'unica tabella 'OrganizationTree'. ha anche il vantaggio di utilizzare una singola query senza modifiche per la ricerca a livello categoria, sottocategoria, o di organizzazione (per esempio darmi tutti i risultati di X sottocategoria)

Spero che questo aiuti.

Adam.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top