Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> struktura drzewa
pero
post
Post #1





Grupa: Zarejestrowani
Postów: 91
Pomógł: 0
Dołączył: 17.02.2007

Ostrzeżenie: (0%)
-----


witam
mam taka tabele

kategoria
--------
id_kategoria (PK)
id_rodzica (FK)
nazwa

wiecie moze jak za pomoca jednego zapytania sql wyswietlic wysztkie podkategorie ktorych rodzicem jest kategoria o id=1 ?
szukalem na forum i zwykle ludzie pisza zeby drzewa a php obslugiwac. ja wolalbym to zalatwic w sql.
macie moze jakis pomysl jak to rozwiazac ?

pozdrawiam
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 14)
mike
post
Post #2





Grupa: Przyjaciele php.pl
Postów: 7 494
Pomógł: 302
Dołączył: 31.03.2004

Ostrzeżenie: (0%)
-----


Poczytaj sobie o Nested Set Model. To da Ci odpowiedź.
Go to the top of the page
+Quote Post
pero
post
Post #3





Grupa: Zarejestrowani
Postów: 91
Pomógł: 0
Dołączył: 17.02.2007

Ostrzeżenie: (0%)
-----


ten przyklad daje odpowiedz w przypadku gdy znam ilosc poziomow, ale co gdy poziomy dodawane sa dymamicznie i nie mam zalozone ze max ilosc poziomow wynosi 4 ?
Go to the top of the page
+Quote Post
cafepl_com
post
Post #4





Grupa: Zarejestrowani
Postów: 80
Pomógł: 0
Dołączył: 17.01.2007

Ostrzeżenie: (0%)
-----


Osobiście używam takiego kodu (jeszcze ani razu mnie nie zawiódł):

  1. <?php
  2. function showSubCategories($cat_id, $dashes = ''){
  3.    $dashes .= '----';
  4.    $rsSub = mysql_query("SELECT * FROM tabela WHERE id_rodzica=" . $cat_id) or die(mysql_error());
  5.    if(mysql_num_rows($rsSub) >= 1){
  6.        while($rows_sub = mysql_fetch_array($rsSub)){
  7.            echo '<li>'.$dashes.' '.$rows_sub['nazwa'].'</li>';
  8.            showSubCategories($rows_sub['id_kategoria'], $dashes);
  9.        }
  10.    }
  11.  
  12. }
  13.  
  14.  
  15. echo '<ul>';
  16. $rsMain = mysql_query("SELECT * FROM tabela WHERE id_rodzica=0") or die(mysql_error());
  17. if(mysql_num_rows($rsMain) >= 1){
  18.    while($rows_main = mysql_fetch_array($rsMain)){
  19.    echo '<li>-- '.$rows_main['nazwa'].'</li>';
  20.        showSubCategories($rows_main['id_kategoria']);
  21.    }
  22. }
  23.    echo '</ul>';
  24. ?>


Pozdrawiam.
Go to the top of the page
+Quote Post
ayeo
post
Post #5





Grupa: Przyjaciele php.pl
Postów: 1 202
Pomógł: 117
Dołączył: 13.04.2007
Skąd: 127.0.0.1

Ostrzeżenie: (0%)
-----


Witam!

W bazie trzymaj, id elementu, id rodzica, ścieżkę, i level. Podam przykład:

id parent path level name
1 0 0 0 główny
2 1 1 1 pierwszy poziom
3 2 1.2 2 drugi

Level to w sumie ilość kropek w ścieżce + 1 więc nawet nie musisz tego trzymać. Całą gałąź pobierasz przez LIKE. Na przykład gałąź od elementu id 2: path LIKE 2% Oczywiście musisz używać CONCAT, żeby dodawać kropki przed i po ścieżce bo Ci złapie trochę "nie tych" elementów.

Ścieżka w bazie 1.2.3
CONCAT('.', path, '.') LIKE .1.2.3.% OR path = 1.2.3

Jest to sposób banalny w implemantacji. Wszystkie operacje (dodawanie, przenoszenie całych gałęzi, usuwanie gałęzi...) są proste i przyjemne. Rozwiązanie jest nawet, można powiedzieć, wydajne smile.gif


Pozdrawiam!


--------------------
Go to the top of the page
+Quote Post
kbsucha
post
Post #6





Grupa: Zarejestrowani
Postów: 113
Pomógł: 19
Dołączył: 2.08.2007

Ostrzeżenie: (0%)
-----


ayeo jak to własnie jest z wydajnościa tej metody, bo ogólnie LIKE nie jest uważany za najszczęśliwsze rozwiązanie dla bazy?

pozdr


--------------------
Go to the top of the page
+Quote Post
ayeo
post
Post #7





Grupa: Przyjaciele php.pl
Postów: 1 202
Pomógł: 117
Dołączył: 13.04.2007
Skąd: 127.0.0.1

Ostrzeżenie: (0%)
-----


LIKE jest ok, gorzej z REGEXpami. Kwestia dobrych indexów wydaje mi się. Trzeba by zrobić testy.


--------------------
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #8





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


LIKE "asdasd%" skorzysta z indeksu - bo poczatek stringa jest znany, i przegladamy tyko stringi zaczynajace sie na "asdasd", a ze mamy jes poukladane to szybko sie do nich dostaniemy
LIKE "%adasdasd" nie skorzysta - poczatek stringa nie jest znany, wiec musimy przejrzec cala tabele


--------------------
Nie lubię jednorożców.
Go to the top of the page
+Quote Post
Black-Berry
post
Post #9





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Wszystko pięknie ale co jeśli chcemy przenieść kawałek drzewa w inne miejsce? Wtedy trzeba zmienić wartość 'path' dla każdego węzła i wydaje mi się, że nie będzie to wtedy prosta sprawa prawda? Przy zastosowaniu left_node, right_node też nie ma łatwo ale jak się dobrze pokombinuje to można każdą operację (typu add, remove, update, move, copy) wykonać w 1-3 zapytania (a przynajmniej w liczbie nierosnącej przy wzroście ilości węzłów).

Ma ktoś większe (albo chociaż mniejsze) doświadczenie z drzewami? Jakiej metody używacie?

Ten post edytował Black-Berry 10.11.2008, 09:58:02


--------------------
Go to the top of the page
+Quote Post
ayeo
post
Post #10





Grupa: Przyjaciele php.pl
Postów: 1 202
Pomógł: 117
Dołączył: 13.04.2007
Skąd: 127.0.0.1

Ostrzeżenie: (0%)
-----


@Black-Berry, a co za problem? Jednym zapytaniem robisz UPDATE i tyle...

Przykład:
1.2.3.4.5 - Mama
1.2.3.4.5.6. - Jaś
1.2.3.4.5.7 - Kubuś

10.11 - Inna mama smile.gif

Przenosimy element o id 5 do elementu o id 11. W ścieżce w bazie nie ma id elementu (czyli path Mama = 1.2.3.4). Robimy UPDATE wszystkich elementów z path 1.2.3.4.5% (szczegóły wyżej, trik z CONCAT), zamieniając w path 1.2.3.4 na 10.11. Jedno zapytanie, nie widzę problemu...

Pozdrawiam!


--------------------
Go to the top of the page
+Quote Post
Black-Berry
post
Post #11





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Fakt, nie pomyślałem o CONCAT. Sposób wydaje się nie mieć wad poza wydajnościowymi. Może ma ktoś dokładne wyliczenia co? Jak to się ma do sposobu z left, right?


--------------------
Go to the top of the page
+Quote Post
tomek_
post
Post #12





Grupa: Zarejestrowani
Postów: 40
Pomógł: 4
Dołączył: 6.11.2008
Skąd: Bytom

Ostrzeżenie: (0%)
-----


sam ostatnio miałem problem ze struktura drzewiastą w MySQL-u 

wszystko da się załatwić dzięki procedurom składowanym smile.gif

tu link do topiku http://forum.php.pl/index.php?showtopic=106515&st=0

w linku który dostałem w odpowiedzi jest kilka fajnych przykładów jak sobie z tym poradzić 

Ten post edytował tomek_ 17.11.2008, 14:47:12


--------------------
Dysortografik -> nie besztać za błędy ;P

pomogłem ? -> kliknij "pomógł" ;)
Go to the top of the page
+Quote Post
Zyx
post
Post #13





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Algorytm przechodzenia drzewa zmodyfikowaną metodą preorder. Każdemu wierszowi przyporządkowujesz dwie unikalne liczby: left i right o następujących własnościach:

1. Dla każdego węzła left < right
2. Dla każdego potomka Y węzła X zachodzą warunki Y.left > X.left, Y.left < X.right, Y.right > X.left, Y.right < X.right (czyli wartości left, right potomków zawierają się w przedziale left-right węzła X).

Wyświetlenie takiego drzewka to kwestia dwóch zapytań, analogicznie bardzo łatwo można odpowiadać na sporo pytań dotyczących danego drzewa (ścieżka do korzenia, ilość potomków itd.), lecz zarządzanie danymi jest już nieco skomplikowane.

Opis algorytmu można znaleźć tutaj: http://artykuly.zyxist.com/czytaj.php/drzewa_w_php_i_mysql

Osobiście dodatkowo dorzucam do tego pole parent_id, które pozwala na pobranie dzieci danego węzła oraz prostsze określenie rodzica.


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post
Black-Berry
post
Post #14





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


no tak, insert w przypadku nested tree jest prosty. Ktoś próbował, przenoszenie gałezi, usuwanie i zmianę pozycji węzła? Moze ma ktos kompletną bibliotekę którą mógłby się podzielić. Chcętnie też nawiązałbym współpracę z kimś kto chciałby taką klase stworzyć na spółkę.


--------------------
Go to the top of the page
+Quote Post
Zyx
post
Post #15





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Próbowałem i zrobiłem:
- usuwanie jest proste - odwrotność dodawania. Zamiast robić dziurę na nowy węzeł, po prostu wycinasz nowy węzeł i kasujesz po nim dziurę w numeracji.
- zmiana kolejności dzieci w obrębie tej samej gałęzi, przenoszenie - to jest już bardziej skomplikowane, gdyż zapytań jest tam trochę, ale po rozrysowaniu sobie, jak zamieniać które wartości, da się napisać. Szczegółów w tej chwili nie pamiętam - musiałbym do kodu zajrzeć i prześledzić, jak to się tam robi.

Niestety biblioteki nie mogę Ci udostępnić, ponieważ jest to integralna część stworzonego jakiś czas temu CMS-a. Za to, o ile dobrze pamiętam, Doctrine posiada wbudowane ogólne wsparcie dla tego typu struktur. Jeśli chciałbyś to jednak pisać samemu, dam jeszcze na wszelki wypadek dobrą radę: transakcje są obowiązkowe smile.gif.


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.08.2025 - 13:23