Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Nested tree - pobieranie węzłów z tego samego poziomu
Forum PHP.pl > Forum > Bazy danych > MySQL
batman
Od pewnego już czasu męczę się z drzewkiem kategorii. Drzewko oparte jest o hierarchię opisaną przy użyciu nested tree.
Struktura bazy:
Kod
mysql> describe tabdocumenttree;
+--------+--------------+------+-----+---------+----------------+
| Field  | Type         | Null | Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
| idnode | int(11)      | NO   | PRI | NULL    | auto_increment |
| sname  | varchar(250) | NO   |     | NULL    |                |
| nleft  | int(11)      | NO   |     | NULL    |                |
| nright | int(11)      | NO   |     | NULL    |                |
| nlevel | int(11)      | NO   |     | NULL    |                |
+--------+--------------+------+-----+---------+----------------+


Jedyne co udało mi się napisać, to pobranie wszystkich elementów, które posiadają rodzeństwo. Mi zależy na pobraniu tylko elementów dla zadanego idnode.
  1. SELECT
  2. node.*
  3. FROM tabdocumenttree AS parent,
  4. tabdocumenttree AS node
  5. WHERE node.nleft > parent.nleft AND node.nright < parent.nright AND parent.nlevel = (node.nlevel - 1)

Jakieś sugestie?


edit
Czasami wystarczy wytłumaczyć komuś o co chodzi i rozwiązanie samo się nasuwa na myśl. Dodałem jeszcze jedno zapytanie i zrobiłem z tego procedurę.
  1. DELIMITER $$
  2.  
  3. DROP PROCEDURE IF EXISTS `cms`.`documenttree_get_siblings`$$
  4. CREATE PROCEDURE `cms`.`documenttree_get_siblings` (IN nodeId INT)
  5. BEGIN DECLARE parentLeft, parentRight, parentLevel INTEGER;
  6.  
  7. SELECT
  8. parent.nleft, parent.nright, parent.nlevel
  9. INTO parentLeft, parentRight, parentLevel
  10. FROM tabdocumenttree AS parent,
  11. tabdocumenttree AS node
  12. WHERE node.idnode = nodeId AND node.nleft > parent.nleft AND node.nright < parent.nright AND parent.nlevel = (node.nlevel - 1);
  13.  
  14. SELECT * FROM tabdocumenttree WHERE nleft > parentLeft AND nright < parentRight AND nlevel = parentLevel + 1;
  15. END$$
  16.  
  17. DELIMITER ;

Jak na razie działa bez zarzutu. Może znacie jakieś prostsze rozwiązanie?
webdice
Dorób sobie kolumnę parent, myślałem kiedyś nad zapytaniem wyciągającym poziom zagłębień danej kategorii, ale doszedłem do wniosku że jest to bez sensu.

EDIT: Trochę źle się wyraziłem. Wszystko w następnym poście.
batman
Nie do końca rozumiem o co Ci chodzi z poziomem zagłębień. Jeśli o to, by określić, na jakim poziomie znajduje się dany węzeł, to załatwia to ten kod
  1. SELECT
  2. (count(parent.idnode) - 1) AS ndepth
  3. FROM tabdocumenttree AS node,
  4. tabdocumenttree AS parent
  5. WHERE node.nleft BETWEEN parent.nleft AND parent.nright AND node.idnode = 11
  6. ORDER BY parent.nleft;
webdice
Nie wiem czy ja Cie dobrze zrozumiałem. Przykładowo mamy:

Kod
| - Kategoria 1
| --- Kategoria 1.1
| ------ Kategoria 1.1.1
| ------ Kategoria 1.1.2
| --- Kategoria 1.2
| ------ Kategoria 1.2.1
| ------ Kategoria 1.2.2
| - Kategoria 2
| --- Kategoria 2.1
| --- Kategoria 2.2


Czy Tobie chodzi o to, aby pobrać przykładowo Kategoria 1.1.1 oraz Kategoria 1.1.2 na podstawie ID Kategoria 1.1?
batman
Nasz poziom komunikacji jest co najmniej zabawny winksmiley.jpg
Źle opisałem problem. Chodziło mi o to, że znając id elementu Kategoria 1.2.1, chcę pobrać wszystkie elementy z tego samego poziomu, czyli Kategoria 1.2.1 i Kategoria 1.2.2, a dla id elementu Kategoria 1.1, pobrać Kategoria 1.1 i Kategoria 1.2. Najlepszym rozwiązaniem byłoby wykonanie tego przy pomocy jednego zapytania, ale chciałbym uniknąć zagnieżdżania zapytań. Poza tym nie chcę dodawać parentId to tabeli, ponieważ nie tylko ja będę pracował na tym drzewie. A wiem, że ludziom nie będzie się chciało myśleć i będą robić iteracyjne zapytania, np po to, by wybrać ścieżkę.
osiris
Może się przydać:
http://www.artfulsoftware.com/mysqlbook/sa...sqled1ch20.html
webdice
  1. SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth
  2. FROM nested_category AS node,
  3. nested_category AS parent,
  4. nested_category AS sub_parent,
  5. (
  6. SELECT node.name, (COUNT(parent.name) - 1) AS depth
  7. FROM nested_category AS node,
  8. nested_category AS parent
  9. WHERE node.lft BETWEEN parent.lft AND parent.rgt AND node.name = 'PORTABLE ELECTRONICS'
  10. GROUP BY node.name
  11. ORDER BY node.lft
  12. )AS sub_tree
  13. WHERE node.lft BETWEEN parent.lft AND parent.rgt AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt AND sub_parent.name = sub_tree.name
  14. GROUP BY node.name
  15. HAVING depth <= 1
  16. ORDER BY node.lft;


Źródło: http://dev.mysql.com/tech-resources/articl...hical-data.html
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.