Eine Ebene bei Nested Sets
am 23.07.2007 14:31:42 von Peter Mairhofer
Hallo!
Ich habe eine Baumstruktur mit Hilfe von Nested Sets gespeichert.
Jetzt benötige ich von einem bestimmten Element alle Kinder einer Ebene
(d.h. nur die Kinder der Ebene unter dem abzufragenden Element und nicht
die komplette Baumstruktur dahinter).
Bis jetzt löse ich es mit folgender Abfrage:
SELECT COUNT( p.categoryID ) -1 AS `level` , `o`. *
FROM `th_categories` AS `n`
INNER JOIN `th_categories` AS `p`
INNER JOIN `th_categories` AS `o`
WHERE (
p.lft < o.lft
AND p.rgt > o.lft
)
AND (
n.lft < o.lft
AND n.rgt > o.lft
)
AND (
n.categoryID = -1
)
GROUP BY `o`.`lft`
)
ORDER BY `o`.`lft` ASC
LIMIT 0 , 30
Ich lese mit obiger Abfrage die Ebene ("level") aus. Dann setze ich die
gleiche Abfrage noch einmal ab und füge ein
HAVING COUNT(p.categoryID)-1 = $ausgelesene_ebene
hinzu. Das ist aber irgendwie genau das Gegenteil von elegant :-(
Gibts da eine Möglichkeit das mit einer Query zu schaffen?
Vielen Dank!
Peter
Re: Eine Ebene bei Nested Sets
am 24.07.2007 09:53:01 von Daniel Fischer
Peter Mairhofer!
> Jetzt benötige ich von einem bestimmten Element alle Kinder einer Ebene
> (d.h. nur die Kinder der Ebene unter dem abzufragenden Element und nicht
> die komplette Baumstruktur dahinter).
[...]
> Gibts da eine Möglichkeit das mit einer Query zu schaffen?
Ungetestet - und das .id wirst du ersetzen müssen, mir war nicht klar ob
..categoryID das richtige gewesen wäre:
SELECT node.id, (COUNT(parent.id) - (subtree.depth + 1)) AS depth
FROM th_categories AS node,
th_categories AS parent,
th_categories AS subparent,
( SELECT node.id, (COUNT(parent.id) - 1) AS depth
FROM tree AS node, tree AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.id = nodeid
GROUP BY node.id ORDER BY node.lft
) AS subtree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.lft BETWEEN subparent.lft AND subparent.rgt
AND subparent.id = subtree.id
GROUP BY node.id
HAVING depth = 1
ORDER BY node.lft;
Die Spalte "depth" wirst du im Ergebnis allerdings einfach ignorieren
müssen, die ist ohne das HAVING depth = 1 am Ende spannender :-)
Daniel
Re: Eine Ebene bei Nested Sets
am 25.07.2007 23:45:37 von Peter Mairhofer
Daniel Fischer dixit:
> Peter Mairhofer!
>
>> Jetzt benötige ich von einem bestimmten Element alle Kinder einer
>> Ebene (d.h. nur die Kinder der Ebene unter dem abzufragenden Element
>> und nicht die komplette Baumstruktur dahinter).
> [...]
>> Gibts da eine Möglichkeit das mit einer Query zu schaffen?
>
> Ungetestet - und das .id wirst du ersetzen müssen, mir war nicht klar
> ob .categoryID das richtige gewesen wäre:
>
> SELECT node.id, (COUNT(parent.id) - (subtree.depth + 1)) AS depth
> FROM th_categories AS node,
> th_categories AS parent,
> th_categories AS subparent,
> ( SELECT node.id, (COUNT(parent.id) - 1) AS depth
> FROM tree AS node, tree AS parent
> WHERE node.lft BETWEEN parent.lft AND parent.rgt
> AND node.id = nodeid
> GROUP BY node.id ORDER BY node.lft
> ) AS subtree
> WHERE node.lft BETWEEN parent.lft AND parent.rgt
> AND node.lft BETWEEN subparent.lft AND subparent.rgt
> AND subparent.id = subtree.id
> GROUP BY node.id
> HAVING depth = 1
> ORDER BY node.lft;
>
> Die Spalte "depth" wirst du im Ergebnis allerdings einfach ignorieren
> müssen, die ist ohne das HAVING depth = 1 am Ende spannender :-)
Wooow danke!
Funktioniert praechtig! Hab auch ganz vergessen dass mySQL 5 schon
verschachtelte SELECTs unterstuetzt...
Dafuer stellts jetzt Zend_Db_Select auf bei der verschachtelten Abfrage
;-) Is nun die einzige "direkte" SQL Abfrage in meiner Anwendung :-)
lg,
Peter