sql >> Database >  >> RDS >> PostgreSQL

hiërarchische gegevens klonen

Dit resultaat recursief ophalen is lastig (hoewel mogelijk). Het is echter meestal niet erg efficiënt en er is een veel betere manier om dit probleem op te lossen.

Kortom, je vergroot de tabel met een extra kolom die de boom naar de top volgt - ik noem het de "Upchain". Het is gewoon een lange string die er ongeveer zo uitziet:

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:

Het is heel eenvoudig om dit veld up-to-date te houden door een trigger op de tafel te gebruiken. (Excuses voor de terminologie, maar ik heb dit altijd gedaan met SQL Server). Telkens wanneer u een record toevoegt of verwijdert, of het veld parent_id bijwerkt, hoeft u alleen het upchain-veld op dat deel van de boom bij te werken. Dat is een triviale taak omdat je gewoon de upchain van het bovenliggende record neemt en de id van het huidige record toevoegt. Alle onderliggende records kunnen gemakkelijk worden geïdentificeerd met LIKE om te controleren op records met de starttekenreeks in hun upchain.

Wat u effectief doet, is een beetje extra schrijfactiviteit inruilen voor een grote opslaan wanneer u de gegevens komt lezen.

Als je een volledige tak in de boom wilt selecteren, is dat triviaal. Stel dat u de vertakking onder knooppunt 1 wilt hebben. Knooppunt 1 heeft een upchain '1:', dus u weet dat elk knooppunt in de tak van de boom onder dat knooppunt een upchain moet hebben die begint met '1:...'. Dus je doet gewoon dit:

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

Dit is extreem snel (indexeer natuurlijk het upchain-veld). Als bonus maakt het ook veel activiteiten uiterst eenvoudig, zoals het vinden van gedeeltelijke bomen, het niveau in de boom, enz.

Ik heb dit gebruikt in applicaties die grote rapportagehiërarchieën van werknemers bijhouden, maar je kunt het voor vrijwel elke boomstructuur gebruiken (uitsplitsing van onderdelen, enz.)

Opmerkingen (voor iedereen die geïnteresseerd is):

  • Ik heb geen stap voor stap van de SQL-code gegeven, maar als je het principe eenmaal doorhebt, is het vrij eenvoudig te implementeren. Ik ben geen geweldige programmeur, dus ik spreek uit ervaring.
  • Als u al gegevens in de tabel heeft, moet u een eenmalige update uitvoeren om de upchains in eerste instantie te synchroniseren. Nogmaals, dit is niet moeilijk omdat de code erg lijkt op de UPDATE-code in de triggers.
  • Deze techniek is ook een goede manier om kringverwijzingen te identificeren die anders lastig te herkennen zijn.


  1. regexp_split_to_table en row_number

  2. Hoe output onderdrukken en controleren of een commando succesvol is?

  3. Sqlalchemy AttributeError:'property' object heeft geen attribuut 'translate'

  4. Migreren van MySQL naar PostgreSQL