Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL] Jak ułożyć zapytanie?
Forum PHP.pl > Forum > Przedszkole
thomson89
Witam!

Mam taka prostą tabelkę z kilkoma testowymi wartościami. I muszę takie zapytanie i nie wiem jak to zrobić.


Chciałbym mieć podaną nazwy kategorii z ich przyporządkowaniem.
Np. 4 -> 3 -> 1, 1 -> 3 oraz np. 1 -> 5.

Muszę zrobić coś takiego (do tego jest potrzebne to zapytanie)
kategoria 1
-->kategoria 2
----->kategoria 3
----->kategoria 7
----->kategoria 8
-------->kategoria 9
-------->kategoria 10
-->kategoria 6
kategoria 4
kategoria 5

Coś na styl drzewka. Proszę o pomoc!

----------

Skoro żaden kolega nie chce pomoc, sprobowałem własnych sił.

Wydziergałem:
  1. $polaczenie = new baza;
  2. $query = 'SELECT * FROM kategorie WHERE poziom = 1';
  3. $wynik = mysql_query($query);
  4.  
  5. print '<ul>';
  6. while($row = mysql_fetch_assoc($wynik))
  7. {
  8. print '<li>'.$row['nazwa'];
  9. $query_p2 = 'SELECT * FROM kategorie WHERE poziom = 2 AND id_kategori_wyzszej = '.$row['id'];
  10. $wynik_p2 = mysql_query($query_p2);
  11. if(mysql_num_rows($wynik_p2) > 0)
  12. {
  13. print '<ul>';
  14. while($row_p2 = mysql_fetch_assoc($wynik_p2))
  15. {
  16. print '<li>'.$row_p2['nazwa'];
  17. $query_p3 = 'SELECT * FROM kategorie WHERE poziom = 3 AND id_kategori_wyzszej = '.$row_p2['id'];
  18. $wynik_p3 = mysql_query($query_p3);
  19. if(mysql_num_rows($wynik_p3) > 0)
  20. {
  21. print '<ul>';
  22. while($row_p3 = mysql_fetch_assoc($wynik_p3))
  23. {
  24. print '<li>'.$row_p3['nazwa'].'</li>';
  25. $query_p4 = 'SELECT * FROM kategorie WHERE poziom = 4 AND id_kategori_wyzszej = '.$row_p3['id']; $wynik_p4 = mysql_query($query_p4);
  26. if(mysql_num_rows($wynik_p4) > 0)
  27. {
  28. print '<ul>';
  29. while($row_p4 = mysql_fetch_assoc($wynik_p4))
  30. {
  31. print '<li>'.$row_p4['nazwa'];
  32. $query_p5 = 'SELECT * FROM kategorie WHERE poziom = 5
  33. AND id_kategori_wyzszej = '.$row_p4['id'];
  34. $wynik_p5 = mysql_query($query_p5);
  35. if(mysql_num_rows($wynik_p5) > 0)
  36. {
  37. print '<ul>';
  38. while($row_p5 = mysql_fetch_assoc($wynik_p5))
  39. {
  40. print '<li>'.$row_p5['nazwa'].'</li>';
  41. }
  42. print '</ul>';
  43. }
  44. print '</li>';
  45. }
  46. print '</ul>';
  47. }
  48. print '</li>';
  49. }
  50. print '</ul>';
  51. }
  52. print '</li>';
  53. }
  54. print '</ul>';
  55. }
  56. print '</li>';
  57. }
  58. print '</ul>';
taro
W Oracle jest coś takiego jak CONNECT BY PRIOR. Nie wiem jak zrobić coś takiego w MySQL, ale ten CONNECT BY PRIOR w Oracle powinien tutaj pomóc. Poszukaj może w google itp. Jeżeli dobrze pamiętam to właśnie to generowało coś podobnego, co potrzebujesz (drzewko z węzłami...)

Krótki przykład:

Podac dla pracownika o numerze 7369 jego zwierzchnikow oraz numer wezla

SELECT EMPNO, ENAME, level FROM EMP CONNECT BY PRIOR mgr=empno START WITH empno=7369;

Nie jestem pewien, czy to jest coś takiego w 100%, ale powinno dać jakieś natchnienie. ;-)

Pozdrawiam.
za017
Po pierwsze w Twojej tabeli pole `poziom` jest raczej zbędne, na pewno nie jest potrzebne do wygenerowania struktury drzewa, wynika ona z samego powiązania `id` i `id_kategorii_wyzszej`. Kwestia prostoty: zamiast `id_kategorii_wyzszej` użyj pola o nazwie `pid` (od `parent id`), które będzie indeksowane, np:

  1. CREATE TABLE kategorie(
  2. id INT UNSIGNED NOT NULL,
  3. pid INT UNSIGNED NOT NULL,
  4. nazwa VARCHAR(255),
  5. PRIMARY KEY(id),
  6. INDEX(pid)
  7. );
  8. --
  9. -- przykładowe dane
  10. --
  11. INSERT INTO kategorie VALUES(1, 0, 'Kategoria 1');
  12. INSERT INTO kategorie VALUES(2, 0, 'Kategoria 2');
  13. INSERT INTO kategorie VALUES(3, 0, 'Kategoria 3');
  14. INSERT INTO kategorie VALUES(4, 0, 'Kategoria 4');
  15. INSERT INTO kategorie VALUES(5, 0, 'Kategoria 5');
  16. INSERT INTO kategorie VALUES(6, 2, 'Kategoria 2.1');
  17. INSERT INTO kategorie VALUES(7, 2, 'Kategoria 2.2');
  18. INSERT INTO kategorie VALUES(8, 2, 'Kategoria 2.3');
  19. INSERT INTO kategorie VALUES(9, 7, 'Kategoria 2.2.1');
  20. INSERT INTO kategorie VALUES(10, 7, 'Kategoria 2.2.2');
  21. INSERT INTO kategorie VALUES(11, 7, 'Kategoria 2.2.3');
  22. INSERT INTO kategorie VALUES(12, 4, 'Kategoria 4.1');


Po drugie zawsze należy dążyć do ograniczenia ilości zapytań wysyłanych do bazy danych: w miarę wzrostu ich ilości komunikacja z serwerem baz danych staje się wąskim gardłem aplikacji. Strukturę drzewiastą można wygenerować za pomocą samego PHP (gwarantuję Ci, że będzie to działało kilka razy szybciej, wielokrotnie się o tym przekonałem) i tylko JEDNEGO zapytania do bazy danych.

Aby to zrobić musimy zbudować w PHP tablicę, wykonując małą sztuczkę z polem `pid`: każdy kolejny rekord pobrany z bazy danych, wczytujemy do 'tablica[pid]', dzięki czemu zgromadzimy w jednym miejscu wszystkie elementy o danych pid i będziemy mogli je łatwo pobrać z tablicy. Taką możliwość daje nam niezwykła elastyczność tablic w PHP.

  1. <?php
  2. /*
  3.  * Wersja proceduralna (bardzo nielegancka)
  4.  * UWAGA: nie ma żadnego ograniczenia na ilość kategorii (głębokość drzewa)
  5.  */
  6.  
  7. // Pobieramy dane z bazy danych:
  8.  
  9. $db = new mysqli('localhost','user','password','testy');
  10. $ans = $db->query('SELECT * FROM kategorie');
  11.  
  12. /*
  13.   * Budujemy model danych, w tym wypadku tablicę o strukturze:
  14.   * $tablica[parent_id] = { lista potomków }
  15.   */
  16.  
  17. while($row = $ans->fetch_row())
  18. {
  19. if(!$model[$row[1]])
  20. {
  21. $model[$row[1]] = array();
  22. }
  23. array_push($model[$row[1]],$row);
  24. }
  25.  
  26. // Mając dane możemy wygenerować widok:
  27.  
  28. echo '
  29. <html>
  30. <body>
  31. ';
  32.  
  33. // Elementy o pid==0 (przechowyne w $model[0]) są kategoriami najwyższego rzędu
  34.  
  35. function categoryTreeView(& $model, $pid=0) {
  36. foreach($model[$pid] as $category)
  37. {
  38. echo '<div style="margin-left:25px">'.$category[2];
  39.  
  40. // Sprawdzamy czy dana kategoria ma potomków, jeżeli tak - wywołujemy funkcję rekurencyjnie:
  41.  
  42. if(count($model[$category[0]]))
  43. {
  44. categoryTreeView($model, $category[0]);
  45. }
  46. echo '</div>';
  47. } // ~foreach
  48. }
  49.  
  50. categoryTreeView($model);



Jeżeli piszesz na klasach (obiektowo) to bardziej zaciekawi Cię ta wersja:

  1. <?php
  2. /*
  3.  * Prosta wersja obiektowa
  4.  */
  5.  
  6. class CategoryModel {
  7.  
  8. private $model;
  9.  
  10. public function __construct(mysqli & $db) {
  11. $ans = $db->query('SELECT * FROM kategorie');
  12. while($row = $ans->fetch_row())
  13. {
  14. if(!$this->model[$row[1]])
  15. {
  16. $this->model[$row[1]] = array();
  17. array_push($this->model[$row[1]],$row);
  18. }
  19. }
  20.  
  21. public function hasChildren($parentId) {
  22. return count($this->model[$parentId])>0;
  23. }
  24.  
  25. public function getChildren($parentId = 0) {
  26. return $this->model[$parentId];
  27. }
  28.  
  29. }
  30.  
  31. class CategoryTreeView {
  32.  
  33. private $model;
  34. private $html='';
  35.  
  36. public function __construct(CategoryModel & $model) {
  37. $this->model = $model;
  38. $this->html();
  39. }
  40.  
  41. private function html($pid=0) {
  42. if($children = $this->model->getChildren($pid))
  43. {
  44. foreach($children as $child)
  45. {
  46. $this->html.= '<div style="margin-left:25px">'.$child[2];
  47. if($this->model->hasChildren($child[0]))
  48. {
  49. $this->html($child[0]);
  50. }
  51. $this->html.= '</div>';
  52. } ~foreach
  53. } ~if
  54. }
  55.  
  56. public function __toString() {
  57. return $this->html;
  58. }
  59.  
  60. }
  61.  
  62.  
  63. echo new CategoryTreeView(
  64. new CategoryModel(
  65. new mysqli('localhost','user','password','testy')
  66. )
  67. );

W obu wypadkach wynik będzieidentyczny:
Kategoria 1
Kategoria 2
-->Kategoria 2.1
-->Kategoria 2.2
---->Kategoria 2.2.1
---->Kategoria 2.2.2
---->Kategoria 2.2.3
-->Kategoria 2.3
Kategoria 3
Kategoria 4
-->Kategoria 4.1
Kategoria 5
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.