PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

clonazione di dati gerarchici

Tirare questo risultato in modo ricorsivo è complicato (sebbene possibile). Tuttavia, in genere non è molto efficiente e c'è un molto modo migliore per risolvere questo problema.

Fondamentalmente, aumenti la tabella con una colonna in più che traccia l'albero in alto - lo chiamerò "Upchain". È solo una lunga stringa che assomiglia a questa:

name | id | parent_id | upchain
root1 | 1 | NULL | 1:
root2 | 2 | NULL | 2:
root1sub1 | 3 | 1 | 1:3:
root1sub2 | 4 | 1 | 1:4:
root2sub1 | 5 | 2 | 2:5:
root2sub2 | 6 | 2 | 2:6:
root1sub1sub1 | 7 | 3 | 1:3:7:

È molto facile mantenere aggiornato questo campo utilizzando un trigger sul tavolo. (Mi scuso per la terminologia, ma l'ho sempre fatto con SQL Server). Ogni volta che aggiungi o elimini un record, o aggiorni il campo parent_id, devi solo aggiornare il campo upchain su quella parte dell'albero. Questo è un lavoro banale perché prendi semplicemente la catena a monte del record principale e aggiungi l'id del record corrente. Tutti i record figlio sono facilmente identificabili utilizzando LIKE per verificare la presenza di record con la stringa iniziale nella loro upchain.

Quello che stai facendo in modo efficace è scambiare un po' di attività di scrittura extra con un grande salvando quando vieni a leggere i dati.

Quando vuoi selezionare un ramo completo nell'albero è banale. Supponiamo di volere il ramo sotto il nodo 1. Il nodo 1 ha un upchain '1:' quindi sai che qualsiasi nodo nel ramo dell'albero sotto quel nodo deve avere un upchain che inizia '1:...'. Quindi fai solo questo:

SELECT *
FROM table
WHERE upchain LIKE '1:%'

Questo è estremamente veloce (indicizza il campo upchain ovviamente). Come bonus rende anche molte attività estremamente semplici, come trovare alberi parziali, livellare all'interno dell'albero, ecc.

L'ho usato in applicazioni che tengono traccia di grandi gerarchie di rapporti dei dipendenti, ma puoi usarlo praticamente per qualsiasi struttura ad albero (scomposizione delle parti, ecc.)

Note (per chi è interessato):

  • Non ho fornito un passaggio del codice SQL, ma una volta ottenuto il principio, è piuttosto semplice da implementare. Non sono un grande programmatore, quindi parlo per esperienza.
  • Se hai già dei dati nella tabella, devi eseguire un aggiornamento una tantum per sincronizzare inizialmente le upchain. Anche in questo caso, non è difficile in quanto il codice è molto simile al codice UPDATE nei trigger.
  • Questa tecnica è anche un buon modo per identificare riferimenti circolari che altrimenti potrebbero essere difficili da individuare.