sql >> Database >  >> RDS >> Mysql

Een aantal items van een boom opvragen

Gezien die beperkingen is er geen manier. In een dergelijk geval zou u ofwel alle . terughalen de boom en bouw een 'heuvel'-clientzijde, of voer recursieve query's uit, wat in het specifieke geval het meest efficiënt zou zijn.

Met als extra beperking een vast aantal hiërarchieniveaus hebben , je kunt dit doen met een meervoudige JOIN.

In het algemeen zijn er verschillende structuuraanpassingen om deze beperkingen te omzeilen. In de praktijk versoepelt u de beperking "DIT is mijn tabelstructuur", waardoor u extra velden kunt toevoegen.

U kunt de knooppuntstructuur bijvoorbeeld aanvullen met een left_id waarde, en zorg ervoor dat alle node-ID's op volgorde staan ​​wanneer u de tree depth-first bezoekt:

1 --- 2 -+- 3 -+- 4
         |     |
         |     +- 5
         +- 6 --- 7

In dit geval zou knooppunt 3 de waarde "5" opslaan, knooppunt 6 zou de waarde "7" opslaan en knooppunt 2 zou ook de waarde "7" opslaan. Elk knooppunt slaat in LeftID het maximum op tussen de LeftID's van zijn kinderen en zijn eigen ID .

Dus kinderloze nodes hebben LeftID gelijk aan hun ID's. Knooppunt 1 heeft LeftID 7 omdat dat de LeftID van 2 is, die het van 6 heeft gekregen.

In deze situatie, tellen knooppunten is gemakkelijk als er geen gaten in de reeks zijn; alle afstammelingen van een knoop zijn die knopen waarvan de ID tussen de ID van de startknoop en zijn linkerID ligt; en bladeren worden geïdentificeerd door LeftID gelijk aan ID te hebben.

Dus "alle bladeren die afstammen van knooppunt id 17" zijn

SELECT child.*FROM table AS parentJOIN table AS childON (child.id> parent.id AND child.id <=parent.leftid ) /* Afstammeling /WHERE child.id =child.leftid / Leaf /AND ouder.id =17; / Ouder is 17

Deze structuur is lastig te onderhouden als je wilt kunnen snoeien en vertakken, aangezien je alle knooppunten tussen het snoeipunt tot het vertakkingspunt opnieuw moet nummeren, evenals de verplaatste knooppunten.

Een andere mogelijkheid als u alleen geïnteresseerd bent in tellen, is om een ​​kinderteller bij te houden. Dit kan worden onderhouden door het iteratief bij te werken, alle bladeren te selecteren en hun teller op 0 te zetten (u identificeert bladeren via een LEFT JOIN); dan al die ouders met NULL-tellers die kinderen hebben met niet-NULL-tellers, die hun tellers bijwerken naar de SUM() aantal kindertellers plus de COUNT() van kinderen zelf; en doorgaan totdat het aantal bijgewerkte rijen nul wordt, want alle knooppunten hebben niet-NULL-tellers. Na een snoei-en-tak, zet je alle tellers op NULL en herhaal je.

Deze laatste benadering kost een reflectieve deelname voor elk hiërarchieniveau.



  1. SQL om een ​​samengevoegde reeks resultaten te retourneren

  2. Hoe te testen op overlappende datums in PostgreSQL

  3. Python + MySQLdb executemany

  4. lange waarde opslaan in Android-database