Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Drzewo kategorii i wyciąganie danych
zaksmok
post 25.02.2010, 09:34:14
Post #1





Grupa: Zarejestrowani
Postów: 58
Pomógł: 2
Dołączył: 12.01.2006

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


Witam serdecznie. Stoję przed ciężkim problemem jakim jest drzewo kategorii.
Aktualnie korzystam z nested sets + parent_id

Jaki problem?

Mając następującą strukturę:

  1. - Kategoria 1
  2. - Sub 1.1
  3. - SubSub 1.1.1
  4. - SubSub 1.1.2
  5. - SubSubSub 1.1.2.1
  6. - SubSubSub 1.1.2.2
  7. - SubSubSub 1.1.2.3
  8. - Sub 1.2
  9. - SubSub 1.2.1
  10. - SubSub 1.2.2
  11. - Sub 1.3
  12. - Kategoria 2
  13. - Sub 2.1
  14. - SubSub 2.1.1
  15. - SubSub 2.1.2
  16. - Sub 2.2
  17. - Sub 2.3
  18. - Kategoria 3
  19. - Sub 3.1
  20. - Sub 3.2
  21. - Sub 3.3
  22. - Kategoria 4
  23. - Kategoria 5


będąc w kategorii Sub 1.2 powinienen widzieć:

  1. - Kategoria 1
  2. - Sub 1.1
  3. - Sub 1.2
  4. - SubSub 1.2.1
  5. - SubSub 1.2.2
  6. - Sub 1.3
  7. - Kategoria 2
  8. - Kategoria 3
  9. - Kategoria 4
  10. - Kategoria 5


a będąc w kategorii SubSubSub 1.1.2.2

  1. - Kategoria 1
  2. - Sub 1.1
  3. - SubSub 1.1.1
  4. - SubSub 1.1.2
  5. - SubSubSub 1.1.2.1
  6. - SubSubSub 1.1.2.2
  7. - SubSubSub 1.1.2.3
  8. - Sub 1.2
  9. - Sub 1.3
  10. - Kategoria 2
  11. - Kategoria 3
  12. - Kategoria 4
  13. - Kategoria 5


Próby skończyły się na następującym zapytaniu:
  1. SELECT * FROM categories WHERE parent_id IN(NULL, 1) OR lft BETWEEN 3 AND 7)


Przy takim zapytaniu muszę znać:
1. ID głównej gałęzi w nested sets (null lub id = 1, w zależności od struktury nested sets)
2. ID najwyższego rodzica otwartej kategorii (w moim zapytaniu id=1)
3. LFT i RGT najwyższego rodzica kategorii.

Dla struktury
  1. - Kategoria 1
  2. - Sub 1.1
  3. - SubSub 1.1.1
  4. - SubSubSub 1.1.1.1
  5. - SubSubSub 1.1.1.2
  6. - SubSubSub 1.1.1.3
  7. - SubSub 1.1.2
  8. - SubSubSub 1.1.2.1
  9. - SubSubSub 1.1.2.2
  10. - SubSubSub 1.1.2.3
  11. - Sub 1.2
  12. - SubSub 1.2.1
  13. - SubSub 1.2.2
  14. - Sub 1.3
  15. - Kategoria 2
  16. - Sub 2.1
  17. - SubSub 2.1.1
  18. - SubSub 2.1.2
  19. - Sub 2.2
  20. - Sub 2.3
  21. - Kategoria 3
  22. - Sub 3.1
  23. - Sub 3.2
  24. - Sub 3.3
  25. - Kategoria 4
  26. - Kategoria 5


bedąc w SubSubSub 1.1.2.1 powinienen otrzymać

  1. - Kategoria 1
  2. - Sub 1.1
  3. - SubSub 1.1.1
  4. - SubSub 1.1.2
  5. - SubSubSub 1.1.2.1
  6. - SubSubSub 1.1.2.2
  7. - SubSubSub 1.1.2.3
  8. - Kategoria 2
  9. - Kategoria 3
  10. - Kategoria 4
  11. - Kategoria 5



  1. SELECT * FROM categories WHERE parent_id IN (NULL, 1, 2) OR lft BETWEEN 7 AND 10


czyli muszę znać:
1. ID każdego rodzica
2. LFT i RGT najniższego rodzica

i to już mnie przerasta... Może znacie jakiś sprytny sposób na to?

Ten post edytował zaksmok 25.02.2010, 09:37:44
Go to the top of the page
+Quote Post
wiiir
post 25.02.2010, 10:16:49
Post #2





Grupa: Zarejestrowani
Postów: 260
Pomógł: 34
Dołączył: 22.02.2010

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


a jakie masz tabele?

jedna tabela z 4 kolumnami, gdzie kazda kolumna odpowiada za poziom?

Ja jestem zwolennikiem ze nie trzeba sie bac towrzenia i wizania ze soba tabel, wiec zrobil bym 4 table bo mamy 4 kategorie
daje mi to przejrzystosc tabel, zapytan i kodu, wkoncu dlatego bazy nazywaja sie relacyjnymi

  1. 1 petla
  2. warunek
  3. 2 petla
  4. wrunek
  5. 3 petla
  6. warunek
  7. 4 petla

moze ktos powiedziec boze ile zapytan po co itd.. ja wiem z doswiadczenia (oracle+ bardzo duza baza) ze takie zapytania beda wykonywac sie szybiej niz jedno wielkie ktore moze zapchac serwer jak jest zle napisane, w tym ukladnie mozna dodawac odpowiednie warunki kiedy jaki poziom sie wyswietla i dla kogo.. + wile innych plusow
Go to the top of the page
+Quote Post
zaksmok
post 25.02.2010, 12:20:05
Post #3





Grupa: Zarejestrowani
Postów: 58
Pomógł: 2
Dołączył: 12.01.2006

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


gałęzie nie będą aż tak duże, maks 500 rekordów. Wszystko jest w jednej tabeli, struktura nested sets.
Go to the top of the page
+Quote Post
VegetaSSJ
post 25.02.2010, 14:20:56
Post #4





Grupa: Zarejestrowani
Postów: 78
Pomógł: 2
Dołączył: 21.10.2006

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


Cytat(wiiir @ 25.02.2010, 10:16:49 ) *
Ja jestem zwolennikiem ze nie trzeba sie bac towrzenia i wizania ze soba tabel, wiec zrobil bym 4 table bo mamy 4 kategorie
daje mi to przejrzystosc tabel, zapytan i kodu, wkoncu dlatego bazy nazywaja sie relacyjnymi


OMG

Może to ci pomoże:

http://www.phpclasses.org/browse/package/1374.html
http://articles.sitepoint.com/article/hier...l-data-database
http://www.edutech.ch/contribution/nstrees/index.php

Poza tym na moje oko wszystkie kategorie powinny być opakowane jeszcze w nadrzędny element, np root.
Go to the top of the page
+Quote Post
ayeo
post 25.02.2010, 15:34:28
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!

@wiiir, to co proponujesz to jakiś absurd. Dobrych implementacji drzewek jak kilka. Można wybrać coś dla siebie w zależności od potrzeb i trudności. Jak w Twoim pomyśle będziesz realizował przeszukiwanie gałęzi lub przenoszenie? BTW relacją nie jest trzymanie danych tego samego rodzaju w 15 tabelkach.

Co do tematu wątku, mogę polecić jeszcze tzw Drzewka Depesza. Bez trudu znajdziesz w Google materiały. Jest to modyfikacja drzewek IP (taka bardziej zmiana optymalizacyjna). W drzewkach IP chodzi o to, że oprócz id rodzica trzymasz całą ścieżkę jeszcze (np 1.23.345.1224, parent to 1224, kategoria główna to 1). Drzewek LEFT-RIGHT nie mogłem nigdy zrozumieć. Tzn ich fenomenu.

Pozdrawiam!


--------------------
Go to the top of the page
+Quote Post
Methestel
post 25.02.2010, 22:11:11
Post #6





Grupa: Zarejestrowani
Postów: 46
Pomógł: 10
Dołączył: 30.06.2008

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


Problem ciekawy ale rozwiązanie jest dość proste.

Pola przykładowej tablicy 'tbl_tree'
- id
- parent_id
- n_left
- n_right
- level (liczba naturalna informująca o poziomie elementu w drzewie)

Kolumna "level" jest opcjonalna ale zawsze ją dodaję bo znacznie ułatwia wiele operacji na tablicy.



Zapytanie które wyciąga Ci id-ki wszystkich potomków elementu o id = :id już znasz i dla mojej przykładowej tabeli wygląda tak:

  1. SELECT *
  2. FROM tbl_tree
  3. WHERE (n_left > (SELECT n_left FROM tbl_tree WHERE id = :id)
  4. AND n_right < (SELECT n_right FROM tbl_tree WHERE id = :id))


Zapytanie które wyciągnie Ci id-ki wszystkich rodziców elementu o id = :id wygląda identycznie z dwiema drobnymi różnicami (znaki '>' i '<' zamieniły się miejscami):

  1. SELECT *
  2. FROM tbl_tree
  3. WHERE (n_left < (SELECT n_left FROM tbl_tree WHERE id = :id)
  4. AND n_right > (SELECT n_right FROM tbl_tree WHERE id = :id))


Żeby wyciągnąć n_left i n_right (u Ciebie LFT i RGT) najniższego rodzica przeszukujesz wynik poprzedniego zapytania w poszukiwaniu wiersza o najwyższej wartości 'level' lub robisz nowe zapytanie do bazy danych:

  1. SELECT n_left, n_right
  2. FROM tbl_tree
  3. WHERE (n_left < (SELECT n_left FROM tbl_tree WHERE id = :id)
  4. AND n_right > (SELECT n_right FROM tbl_tree WHERE id = :id))
  5. ORDER BY level DESC
  6. LIMIT 1
Go to the top of the page
+Quote Post
Crozin
post 25.02.2010, 22:35:40
Post #7





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

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


Cytat
Drzewek LEFT-RIGHT nie mogłem nigdy zrozumieć. Tzn ich fenomenu.
Cały ich fenomen polega na tym, że część operacji wykonuje się na nich o wiele łatwiej - część oczywiście trudniej. Jest to po prostu kolejna implementacja tego samego mająca swoje wady i zalety.
Go to the top of the page
+Quote Post
cudny
post 25.02.2010, 23:59:25
Post #8





Grupa: Zarejestrowani
Postów: 387
Pomógł: 66
Dołączył: 31.03.2005
Skąd: Kielce

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


A ja bym to rozwiązał rekurencyjnie:
http://forum.php.pl/index.php?showtopic=133135&hl=

pzdr
Cudny


--------------------
..::: Jak pomogłem to kliknij pomógł. Tak rzadko używacie tej opcji :( :::..
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 Wersja Lo-Fi Aktualny czas: 18.07.2025 - 17:10