Eine Ebene bei Nested Sets

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