sql >> Databasteknik >  >> RDS >> PostgreSQL

kloning av hierarkiska data

Att dra in detta resultat rekursivt är knepigt (även om det är möjligt). Men det är vanligtvis inte särskilt effektivt och det finns mycket bättre sätt att lösa detta problem.

I grund och botten utökar du tabellen med en extra kolumn som spårar trädet till toppen - jag kallar det "Upchain". Det är bara en lång sträng som ser ut ungefär så här:

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:

Det är väldigt enkelt att hålla detta fält uppdaterat genom att använda en trigger på bordet. (Ursäkta terminologin men jag har alltid gjort det här med SQL Server). Varje gång du lägger till eller tar bort en post, eller uppdaterar parent_id-fältet, behöver du bara uppdatera upchain-fältet på den delen av trädet. Det är ett trivialt jobb eftersom du bara tar uppkedjan av den överordnade posten och lägger till ID:t för den aktuella posten. Alla underordnade poster är lätta att identifiera med LIKE för att söka efter poster med startsträngen i deras uppkedja.

Vad du effektivt gör är att handla lite extra skrivaktivitet mot en stor sparar när du kommer för att läsa data.

När du vill välja en hel gren i trädet är det trivialt. Anta att du vill ha grenen under nod 1. Nod 1 har en uppkedja '1:' så du vet att vilken nod som helst i grenen av trädet under den noden måste ha en uppkedja som börjar med '1:...'. Så du gör bara så här:

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

Det här är extremt snabbt (indexera uppkedjefältet förstås). Som en bonus gör det också många aktiviteter extremt enkla, som att hitta delträd, nivå inom trädet, etc.

Jag har använt det här i applikationer som spårar stora anställdas rapporteringshierarkier men du kan använda det för i stort sett alla trädstrukturer (delar uppdelning, etc.)

Anteckningar (för alla som är intresserade):

  • Jag har inte gett ett steg-för-steg av SQL-koden, men när du väl förstår principen är det ganska enkelt att implementera. Jag är ingen bra programmerare så jag talar av erfarenhet.
  • Om du redan har data i tabellen måste du göra en engångsuppdatering för att få uppkedjorna att synkronisera initialt. Återigen, detta är inte svårt eftersom koden är väldigt lik UPDATE-koden i triggers.
  • Den här tekniken är också ett bra sätt att identifiera cirkulära referenser som annars kan vara svåra att upptäcka.


  1. FUNCTION SUM finns inte

  2. Åtgärda felet "ORA-01790:uttryck måste ha samma datatyp som motsvarande uttryck"

  3. Allmänt fel:1005 Kan inte skapa tabell med Laravel Schema Build och främmande nycklar

  4. Node.js MSSQL tedius Anslutningsfel:Det gick inte att ansluta till localhost:1433 - anslut ECONNREFUSED