De query werkt door te herhalen over de t_list
tabel (de laatste regel). Voor elke rij in deze tabel, de subquery in de SELECT
clausule vraagt de tabel opnieuw, zoekend naar het onderliggende kind van de huidige rij (WHERE parent = _parent
-- maar _parent
is een alias voor @r
). Bij elke iteratie wordt de id
. van het kind is toegewezen aan de @r
variabel.
Om grenzen toe te voegen, zou deze variatie moeten volstaan:
SELECT * FROM (
SELECT
@r AS _parent,
@r := (
SELECT id
FROM t_list
WHERE
( @c = 0 AND _parent IS NULL AND parent IS NULL ) -- special case if the first item is the root
OR (parent = _parent)
) AS id,
@c := @c + 1 AS rank
FROM (
SELECT @c := 0, @r := parent FROM t_list WHERE id = @start
) AS ini,
(
SELECT id FROM t_list LIMIT @limit
) AS lim
) AS tmp WHERE id IS NOT NULL;
Vervang @start
en @limit
met de id
van het eerste item en het maximale aantal items dat moet worden opgehaald, respectievelijk. test het hier
.
Het modelleren van zo'n datastructuur met een RDBMS is waarschijnlijk helemaal geen slecht idee. Waarom gebruik je niet gewoon een "index"-kolom? Het verkrijgen van de lijst wordt dan onmiddellijk:
SELECT * FROM list ORDER BY index_column ASC;
Misschien is het de bedoeling dat je lijst regelmatig verandert, maar zoekopdrachten als deze zouden redelijk snel moeten zijn, tenzij de lijst erg groot wordt:
-- insert an element at position X
UPDATE list SET index_column = index_column +1 WHERE index_column > X ORDER BY index_column DESC;
INSERT INTO list VALUE (some_value, X);
-- delete an element at position X
DELETE FROM list WHERE index_column = X;
UPDATE list SET index_column = index_column -1 WHERE index_column > X ORDER BY index_column ASC;