Daar hoef je helemaal geen puzzelaar voor te zijn, daarvoor moet je gewoon het juiste data model gebruiken. Een hierarchische boomstructuur op zo'n manier in een database proppen lijkt simpel als je eraan begint, maar kleine taken zijn al nagenoeg niet te doen. Voor wat jij nu wil doen bijvoorbeeld, heb je een ongedefinieerd aantal self joins nodig. En dat is natuurlijk niet te doen. In een SQL query ken ik in elk geval geen goede manier om een recursieve functie te bouwen.
Dus, de oplossing, gebruik een nested set model: http://en.wikipedia.org/wiki/Nested_set_model
Wat lastiger om te bouwen, maar dat werkt in elk geval wel. En voor jouw probleem heb je dan een vrij simpele oplossing:
SELECT b.id
FROM mappen a
LEFT JOIN mappen b ON b.lft BETWEEN a.lft AND a.rgt
WHERE a.id = .... (vul hier het id in van de te verwijderen map)
Wanneer je je database iets beter in elkaar gezet had kon je de Iterator pattern gebruiken om langs alle childs te gaan van een bepaalde map en deze wissen.
Dus, de oplossing, gebruik een nested set model: http://en.wikipedia.org/wiki/Nested_set_model
Wat lastiger om te bouwen, maar dat werkt in elk geval wel. En voor jouw probleem heb je dan een vrij simpele oplossing
Erwin, bedankt voor je verhelderende woord. Ziet er wel lastig uit; hoe bouw je dit terwijl alles variabel is?
Hier kan ik mee verder!
Waar ik altijd mee begin is gewoon de root te definieren. Met een root is het toevoegen van een node in de boom op zich niet zo moeilijk.
Als je een tabel hebt met een id (auto increment), lft, rgt en name veld, dan zou de root bijvoorbeeld 1 (lft), 2 (rgt), 'root' (name) zijn. Wil je dan een node toevoegen dan moet dat dus een child van de root worden en na het toevoegen van de node moeten de lft en rgt waardes als volgt zijn:
lft rgt name
1 4 root
2 3 node1
Wil je dan een node toevoegen als kind van node1, dan krijg je dit:
lft rgt name
1 6 root
2 5 node1
3 4 node2
Hieruit kan je al het patroon opmerken van hoe je de lft en rgt waardes moet aanpassen bij een insert van een nieuwe node. De nieuwe node krijgt als lft waarde de rgt waarde van zijn nieuwe parent, als rgt waarde wordt lft+1 en alle lft en rgt waardes in de boom die groter of gelijk zijn aan de rgt waarde van de nieuwe parent moeten met twee opgehoogd worden. Als sql queries heb je dus dit nodig:
//zorg dat je de rgt waarde van de nieuwe parent weet, die moet overal op de stippellijnen worden ingevuld
UPDATE tree
SET lft = lft+2
WHERE lft > ....
ORDER BY lft DESC;
UPDATE tree
SET rgt = rgt+2
WHERE rgt >= ....
ORDER BY lft DESC;
INSERT INTO tree(lft, rgt, name)
VALUES(..., ...+1, 'nodeX');
De ordering in de update queries is alleen nodig als je een unieke index gebruikt op de lft en rgt kolommen.
Bij voorkeur verpak ik al deze queries in een stored procedure om het bij elkaar te houden en zodat je zeker weet dat je niet een update vergeet.
Als het inserten lukt, dan is de volgende taak om elementen uit de boom te halen. Ook daar zal je de boom moeten herstructureren op een soortgelijke manier.
Als het inserten lukt, dan is de volgende taak om elementen uit de boom te halen. Ook daar zal je de boom moeten herstructureren op een soortgelijke manier.
Als je niets doet aan de lft en rgt waardes dan gaat je hele boomstructuur naar de knoppen.