Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> [php][mysql] wiele-do-wielu: grupowanie wyników, budowy książki telefonicznej ciąg dalszy
lukasz_matysek
post
Post #1





Grupa: Zarejestrowani
Postów: 33
Pomógł: 2
Dołączył: 25.03.2010

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


Piszę książkę telefoniczną w php, używam bazy mysql.
W bazie są trzy tabele:

wpisy, kategorie oraz tabela realizująca relację wiele-do-wielu: kategorieWpisy. W tabeli tej znajdują się ID kontaktów i kategorii.

Załóżmy, że robię selecta dla potrzeb wyświetlenia tablicy z kontaktami i kategoriami:

SELECT wpisy.nazwa, kategorie.nazwa FROM wpisy,kategorie,KategorieWpisy WHERE KategorieWpisy.idkontakt=wpisy.id AND KategorieWpisy.idkategoria=kategorie.id

czyli dostaję wynik w formie jednej tablicy z nazwami kontaktów i kategoriami, do których są przypisane. Tablicę tą obsługuję oczywiście w standardowy sposób fetch_array

Kiedy dany kontakt jest przypisany do więcej niż jednej kategorii, to wynik dotyczący danego kontaktu otrzymuję w formie dwóch wierszy, na przykład:

nazwakontaktu kategoria1
nazwakontaktu kategoria2

Chciałbym, żeby użytkownik zobaczył to w formie:

nazwakontaktu kategoria1,kategoria2

Problem leży w tym, że linijka "kategoria2" jest generowana już za następnym przebiegiem pętli while-mysql_fetch_array. W związku z tym nie wiem co zrobić, aby uzyskać żądany efekt.

Wycinek kodu; wynik zrzucam do zmiennej buforującej i potem wyrzucam echem.

  1. $t=mysql_query("SELECT wpisy.nazwa,kategorie.nazwa FROM KategorieWpisy,wpisy,kategorie WHERE KategorieWpisy.idwpis=wpisy.id AND KategorieWpisy.idkategoria=kategorie.id") or die (mysql_error());
  2. while($y = mysql_fetch_array($t))
  3. {
  4. $output_buffer.="<tr><td>$y[0]</td><td>$y[1]</tr>";
  5. }
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 3)
mortus
post
Post #2





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

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


Można zrobić tak
  1. $query1 = "SELECT wpisy.id AS id_wpisu, wpisy.nazwa AS nazwa_wpisu FROM wpisy";
  2. $results1 = mysql_query($query) or die(mysql_error());
  3. $output_buffer = '';
  4. while($row1 = mysql_fetch_array($result1)) {
  5. $output_buffer .= $row1['nazwa_wpisu'] . ' (';
  6. $query2 = "SELECT kategorie.nazwa AS nazwa_kategorii FROM kategorie LEFT JOIN KategorieWpisy ON KategorieWpisy.idkategoria=kategorie.id WHERE KategorieWpisy.idwpisu={$row1['id_wpisu']}";
  7. $results2 = mysql_query($query2) or die(mysql_error());
  8. $control = 0;
  9. while($row2 = mysql_fetch_array($results2)) {
  10. $output_buffer .= $row2['nazwa_kategorii'];
  11. if($control < (mysql_num_rows() - 1) {
  12. $output_buffer .= ', ';
  13. }
  14. $control++;
  15. }
  16. }
  17. $output_buffer .= ')';


Choć nie wiem, czy będzie to optymalne (najszybsze) rozwiązanie.

Opcjonalnie to co Ty dostajesz w zapytaniu możesz wrzucić do tablicy (array) i później przetwarzać.
  1. while($y = mysql_fetch_array($t)) {
  2. $wpisy[$y[0]] = $y[1];
  3. }
i sprawdź sobie co wypluje
  1. echo '<pre>';
  2. print_r($wpisy);
  3. echo '</pre>';
a będziesz wiedział, jak to "ugryźć".

EDIT: Poprawiłem kod.
@down: ma być tak jak myślisz.

Ten post edytował mortus 30.03.2010, 10:05:44
Go to the top of the page
+Quote Post
lukasz_matysek
post
Post #3





Grupa: Zarejestrowani
Postów: 33
Pomógł: 2
Dołączył: 25.03.2010

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


Z tego co widzę, proponujesz osobno pozyskiwać kolejne nazwy wpisów, a potem doklejać do tego w zmiennej buforującej wyszukane nazwy kategorii.

w związku z tym _prawdopodobnie_ wiersz 4 powinien wyglądać tak:
  1. while($row1 = mysql_fetch_array($results1)) {

albo się mylę. Popraw mnie jeżeli źle to rozumiem.

Pomysł jak najbardziej logiczny i bardzo mi się podoba, chociaż zwielokrotnia to ilość wykonanych zapytań i z pewnością nie jest, jak sam powiedziałeś, najbardziej optymalnym rozwiązaniem. Mimo to książka, którą piszę będzie używana na maksymalnie 10 stanowiskach w sieci lokalnej i to rzadko jednocześnie, więc temat wydajności mogę lżej potraktować.

Tak jak pisałem, ta koncepcja bardzo mi się podoba i pewnie z niej skorzystam. Jednak zainteresował mnie też drugi pomysł - zrzucenie całego wyniku do tablicy, przetworzenie jej i wyrzucenie na ekran. Mam w związku z tym pomysłem pytanie o wydajność po stronie serwera: załóżmy większe obciążenie bazy, rzędu kilkaset klientów klikających po książce w której jest kilkaset rekordów. Co się dzieje z ramem (-lub cache'm - nie wiem smile.gif ) na serwerze, kiedy serwer jest zmuszony przechowywać tak duże zmienne tablicowe?

Tal czy inaczej, dzięki za pomoc, twój post rozwiązał problem.

Ten post edytował lukasz_matysek 30.03.2010, 09:59:05
Go to the top of the page
+Quote Post
mortus
post
Post #4





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

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


Oczywiście trzeba się zastanowić nad sensownym mechanizmem cache'owania takiej dużej tablicy, bo po co ją setki razy generować. Kilkaset wpisów, to raczej nie jest problem (choć to zależy przede wszystkim od "mocy" serwera), problemem będzie kilka tysięcy wpisów. Zauważ tylko, że już przy kilkuset wpisach koniecznością staje się stworzenie stronicowania, bo weź wyświetl kilkaset wpisów jednym ciągiem. A wykorzystując mechanizm stronicowania nie musimy generować, aż tak dużych tablic (podobnie przetwarzanie zapytań do bazy danych nie będzie już "tak nieoptymalne").
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: 19.08.2025 - 17:08