Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ROZWIĄZANY] Dane z wielu tabel i sortowanie wg. kolumny z wybranej tabeli
Forum PHP.pl > Forum > PHP
wbeatn
Witam.

Zlecono mi dodanie paru rzeczy do pewnego serwisu z ogłoszeniami. Niestety jedną z kluczowych modyfikacji jest wprowadzenie możliwości sortowania.
Niestety dlatego, że autor strony, aby wygenerować tabelę HTML z listą dodanych do bazy ogłoszeń skorzystał z wczytywania danych z kilku różnych tabel MySQL pakując pobrane dane do jednej tabeli wygenerowanej do HTML. Jest teraz problem z sortowaniem.

Z sortowaniem nie ma problemu jeśli dane do HTML pobierane są z jednej tabeli MySQL. Lecz co zrobić, aby można było w sposobie jakim się posłużył autor skryptu, umożliwić jeszcze sortowanie takiej tabeli na podstawie wybranej kolumny, jeśli zawartość takich kolumn pochodzi z kilku tabel MySQL?

Mam przygotowane już pole SELECT z którego wybiera się metodę sortowania

  1. <select name="sortuj" style="text-transform: none; font-size: 12px" onchange="location = this.value;">
  2. <?php
  3. if(($_SERVER['REQUEST_URI'] == "/") OR ($_SERVER['REQUEST_URI'] == "/index.php")) $char="http://strona.pl/index.php?";
  4. elseif($_GET['sort']) {
  5.  
  6. $char = "".$_SERVER['REQUEST_URI']."";
  7. $char = "http://strona.pl/".str_replace("/","",substr($char, 0, strpos($char, "sort")))."";
  8.  
  9. }
  10. else $char = "http://strona.pl".$_SERVER['REQUEST_URI']."&";
  11. ?>
  12. <option value="<?php echo $_SERVER['REQUEST_URI']; ?>">-----------</option>
  13. <option value="<?php echo $char; ?>sort=zgloszono&order=ASC">Wolny od (rosnąco)</option>
  14. <option value="<?php echo $char; ?>sort=zgloszono&order=DESC">Wolny od (malejąco)</option>
  15. <option value="<?php echo $char; ?>sort=rodzaj&order=ASC">Rodzaj (rosnąco)</option>
  16. <option value="<?php echo $char; ?>sort=rodzaj&order=DESC">Rodzaj (malejąco)</option>
  17. <option value="<?php echo $char; ?>sort=cena&order=ASC">Cena (rosnąco)</option>
  18. <option value="<?php echo $char; ?>sort=cena&order=DESC">Cena (malejąco)</option>
  19. </select>


Po wybraniu danej opcji z pola SELECT wskakuje strona z odpowiednią zawartością zgodną z wartością value pola OPTION, np. [ http://strona.pl/index.php?sort=rodzaj&order=DESC ].

Problem polega na tym, że PHP pętle opiera na zapytaniu z jednej tabeli, a wewnątrz pętli dopiero dobiera resztę danych potrzebnych do wygenerowania tabeli HTML.

  1. <?php
  2.  
  3. if(isset($_GET['sort']) and isset($_GET['order'])) {
  4. $rezultat = "SELECT * FROM wolne_ladunki ORDER BY ".$_GET['sort']." ".$_GET['order']." LIMIT $od, 30";
  5. } else {
  6. $rezultat = "SELECT * FROM wolne_ladunki ORDER BY data_zgloszenia DESC, godzina_zgloszenia DESC LIMIT $od, 30";
  7. }
  8. $wynik = mysql_query($rezultat);
  9.  
  10. $odlicz = 1;
  11. while($row = mysql_fetch_row($wynik)) {
  12.  
  13. $rezultat2 = "SELECT dzien,miesiac,rok,panstwo,miasto,kod FROM zaladunek WHERE id_zaladunek='$row[1]'";
  14. $wynik2= mysql_query($rezultat2);
  15. $row2 = mysql_fetch_row($wynik2);
  16.  
  17. $rezultat3 = "SELECT dzien,miesiac,rok,panstwo,miasto,kod FROM rozladunek WHERE id_rozladunek='$row[2]'";
  18. $wynik3= mysql_query($rezultat3);
  19. $row3 = mysql_fetch_row($wynik3);
  20.  
  21. $rezultat4 = "SELECT rodzaj_ladunku FROM ladunek WHERE id_ladunek='$row[3]'";
  22. $wynik4= mysql_query($rezultat4);
  23. $row4 = mysql_fetch_row($wynik4);
  24.  
  25. $rezultat5 = "SELECT * FROM oplaty WHERE id_oplata='$row[4]'";
  26. $wynik5= mysql_query($rezultat5);
  27. $row5 = mysql_fetch_row($wynik5);
  28.  
  29. $row5[1]; $cena_rozbij = explode(".", $row5[1]); if($cena_rozbij[1]==00) { $cena = $cena_rozbij[0]; } else { $cena=$row5[1]; }
  30.  
  31. ?>
  32. <tr <? if (($odlicz%2)==0) { echo "styler='backrgound:#ddd'"; } else { echo "bgcolor='#e7e7e7'"; }?>>
  33. <td class="tabela_komorka center" width="90">
  34. <div class="table mauto">
  35. <div class="table-cell va-middle" style="background-color: #3aa910; padding: 10px 15px"><i class="icon-inbox text-white" style="font-size: 16px"></i></div>
  36. <div class="table-cell">
  37. <div class="table-row"><strong class="dater bg-darkgrey text-white"><?=$row2[2]?>.<?=$row2[1]?>.<?=$row2[0]?></strong></div>
  38. <div class="table-row"><strong class="dater bg-head text-white"><?=$row3[2]?>.<?=$row3[1]?>.<?=$row3[0]?></strong></div>
  39. </div>
  40. </div>
  41. </td>
  42. <td class="tabela_komorka center" width="130"><?=$row2[3]?><br /><?=ucwords($row2[4])?><br /><?=$row2[5]?></td>
  43. <td class="tabela_komorka center" width="130"><?=$row3[3]?><br /><?=ucwords($row3[4])?><br /><?=$row3[5]?></td>
  44. <td class="tabela_komorka center thistype" width="100"><?=$row4[0]?></td>
  45. <td class="tabela_komorka center" width="100"><strong><?=$row[6]?></strong><br /><?=$row[7]?></td>
  46. <td class="tabela_komorka center" width="114"><? if($row5[2]==1) { echo "<strong>Cena:</strong><br>Do uzgodnienia<br><strong>Płatność:</strong><br>$row5[8]"; } else { echo "<strong>$cena $row5[4]</strong><br>za<br><strong>$row5[6]</strong>"; }?></td>
  47. <td class="tabela_komorka center" width="104"><a class="przycisk_szczegoly btn blue uppercase" style="font-weight: 800; font-size: 10px; font-family: 'Open Sans';" href="index.php?k=wolne-ladunki&szczegoly=<?=$row[0]?>"><i class="icon-eye-open"></i> Zobacz</a></td>
  48. </tr>
  49. <?
  50. $odlicz++;
  51. }
  52.  


Z tego powodu sortowanie łatwo zrobić tylko dla jednej kolumny wygenerowanej tabeli HTML. Sortowanie kolumn z uzupełniającymi tabelę danymi pobieranymi wewnątrz pętli jest dla mnie nie do przejścia. Siedzę nad tym praktycznie już 12h i nawet o krok nie posunąłem się do przodu. Potrafię zrobić jedynie sortowanie jednej kolumny, tej z zapytania generującego pętle.

Czy jest ktoś kto mógłby mi pomóc znaleźć jakieś rozwiązanie? Byłbym wdzięczny.
rad11
Sprobuj skorzystac z : http://tablesorter.com/docs/.
Greg0
To zupełnie nie tak się powinno robić. Jeśli między tymi tabelami zachodzą relacje (a z tego co widzę na pierwszy rzut oka to tak jest) to powinieneś napisać jedno duże zapytanie które by to wszystko pobrało od razu a nie wykonywać po cztery dodatkowe zapytania na jedno wykonanie pętli, przecież tym można zabić serwer. Poczytaj o JOIN

@edit chyba że nie chcesz się bawić w poprawianie back-endu, to w wtedy możesz jak najbardziej skorzystać z rozwiązania od kolegi wyżej czysto front-endowego
wbeatn
Cytat(rad11 @ 5.09.2014, 13:35:20 ) *
Sprobuj skorzystac z : http://tablesorter.com/docs/.


To mnie posortuje jedynie wczytana stronę, a nie całość danych z tabeli w MySQL.
Wczyta się danych 3 strony po 30, a ja będę mógł tylko sortować te wczytane 30.
Ma być sortowanie danych z całego zapytania.

Cytat(Greg0 @ 5.09.2014, 13:38:38 ) *
To zupełnie nie tak się powinno robić. Jeśli między tymi tabelami zachodzą relacje (a z tego co widzę na pierwszy rzut oka to tak jest) to powinieneś napisać jedno duże zapytanie które by to wszystko pobrało od razu a nie wykonywać po cztery dodatkowe zapytania na jedno wykonanie pętli, przecież tym można zabić serwer. Poczytaj o JOIN

@edit chyba że nie chcesz się bawić w poprawianie back-endu, to w wtedy możesz jak najbardziej skorzystać z rozwiązania od kolegi wyżej czysto front-endowego


Więc jeśli chodzi o cały zapis tej pętli, to praktycznie muszę go napisać od nowa i pozbyć się tego syfu, który autor tego kodu zasponsorował mi wewnątrz pętli?
Zatem czeka mnie sporo roboty, znaczy więcej niż przewidywałem.

Jeśli chodzi o to JOIN, to podczas szukania rozwiązania trafiłem na to i w sumie tez dziwiłem się, że nie jest to w ten sposób zrobione. Znaczy się autor skryptu też nie za bardzo. Świadczą m.in. o tym ciągle wyskakujące mi błędy korzystania z przestarzałych komend w kodzie PHP :) Może jakiś zgredziu to pisał. :P

Co do pomysłu kolegi wyżej, to jw. :)

Pyton_000
Bez naprawy zapytań nic nie zdziałasz bo niby jak ?
wbeatn
Cytat(Pyton_000 @ 5.09.2014, 14:28:08 ) *
Bez naprawy zapytań nic nie zdziałasz bo niby jak ?


Przecież napisalem, że to zrozumiałem.

Ale mam teraz związane z tym pytanie. Niby robię według wskazówek ze stron nt. PHP i lipa. Dlaczego wto zapytanie zwraca błąd:

- Warning: mysql_fetch_row() expects parameter 1 to be resource, boolean given in (...) on line 207

questionmark.gif

  1. <?php
  2. $new = "(
  3. SELECT * FROM (SELECT id_wolne_pojazdy,id_zaladunku,id_rozladunku,id_pojazdu,id_oplaty,zgloszone FROM wolne_pojazdy)
  4. UNION
  5. (SELECT panstwo as zal.pan,miasto as zal.mia,kod as zal.kod,od as zal.od FROM zaladunek WHERE id_zaladunek = id_zaladunku)
  6. UNION
  7. (SELECT panstwo as roz.pan,miasto as roz.mia,kod as roz.kod,od as roz.od FROM rozladunek WHERE id_rozladunek = id_rozladunku)
  8. UNION
  9. (SELECT rodzaj_pojazdu FROM pojazd WHERE id_pojazd = id_pojazdu)
  10. UNION
  11. (SELECT cena,cena_do_uzgodniania,id_waluty,id_za_co_oplata,id_rodzaju_platnosci FROM oplaty WHERE id_oplata = id_oplaty)
  12. )";
  13. $wynik = mysql_query($new);
  14.  
  15. while($row = mysql_fetch_row($wynik)) {
  16.  
  17. // (...)
  18.  
  19. }
  20.  
  21. ?>
Turson
  1. $wynik = mysql_query($new) or die(mysql_error());

sprawdz bledy
Pyton_000
Żeś pojechał z tym zapytaniem...
Masz zrobić JOIN tych pierdułkowatych tabelek z 'wolne_ladunki'
wbeatn
Cytat(Pyton_000 @ 5.09.2014, 16:07:38 ) *
Żeś pojechał z tym zapytaniem...
Masz zrobić JOIN tych pierdułkowatych tabelek z 'wolne_ladunki'


Z wolna dotego docieram smile.gif
Przede wszystkim w tak wyglądającym zapytaniu błedem rażącym jest wywoływanie z każdej tabeli różną ilość kolumn. Liczba kolumn musi byc identyczna w każdym wywołanym zapytaniu. Do tego, wymagane jest, aby każdej bazie nadać alias.

To działa

  1. <?php
  2.  
  3. $new = "
  4. (SELECT id_wolne_pojazdy,id_zaladunku,id_rozladunku,zgloszone FROM wolne_pojazdy as wp)
  5. UNION
  6. (SELECT panstwo,miasto,kod,od FROM zaladunek as zal)
  7. UNION
  8. (SELECT panstwo,miasto,kod,do FROM rozladunek as roz)
  9. UNION
  10. (SELECT cena,id_waluty,id_za_co_oplata,id_rodzaju_platnosci FROM oplaty as opl)
  11. ";
  12.  
  13. ?>


Czas pokombinować z JOIN aby tak to pochytać, że wszystko co trzeba będzie wczytane.
Greg0
Za pomocą JOIN łaczysz tabele po ich kluczach w podobny sposób w jakim oryginalnie jest to rozbite na pojedyncze zapytania, zapytanie pierwsze -> id wyniku podstawiasz do drugiego zapytania itd. JOIN działa analogicznie tylko daje możliwość wykonania jednego zapytania, które daje wyniki zbiorczo na raz.
Do testowania zapytań skorzystaj może z czegoś innego niż wykonywanie ich w skrypcie PHP, np. PhpMyAdmin, SQLBuddy, albo desktopowa aplikacja HeidiSQL. Tam układaj zapytanie, które zwróci takie dane i w takiej postaci jakiej potrzebujesz, a potem je tylko przeklej do skryptu, będzie prościej i szybciej.

Przykładowe zastosowanie JOIN
Masz aktualności które znajdują się w kategoriach,
np. "tytul newsa nr 1" w kategorii "Polityka" itp.
Więc masz dwie tabele
"news":
Kod
id | kategoria_id | tytul
1 | 1 | tytul newsa nr 1
1 | 1 | tytul newsa nr 2
1 | 2 | tytul newsa nr 3

"kategorie":
Kod
id | nazwa
1 | Polityka
2 | Informacje z kraju

I zapytaniem
  1. SELECT n.tytul, k.nazwa FROM news AS n
  2. JOIN kategorie AS k ON k.id=n.kategoria_id

Dostajesz wyniki w postaci
Kod
n.tytul | k.nazwa
tytul newsa nr 1 | Polityka
tytul newsa nr 2 | Polityka
tytul newsa nr 3 | Informacje z kraju

wbeatn

GOTOWE ROZWIĄZANIE

Oto gotowe rozwiązanie całego problemu, który został dokładnie opisany we wcześniejszych wypowiedziach.

Jeśli chodzi o sortowanie, trzeba sobie przygotować pole SELECT z opcjami sortowania do wyboru, w których wartości value będą zawierać linki do wybranego sortowania. Poniższy kod PHP umieszony w kodzie pola SELECT powoduje, że w zależności od tego na jakiej jesteśmy stronie do wartości value pola OPTION dodawany jest inny link.

Dzięki temu jeśli jesteśmy na podstronie, która w adresie ma ciąg zmiennych, do wartości value każdego pola OPTION generuje się link z URL do strony, z której wywołujemy sortowanie oraz w zależności od tego na jakiej jesteśmy stronie, dodaje ciąg odpowiedzialny za sortowanie (sort={OPCJA}&order={DESC lub ASC}) poprzedzając go znakiem "&" (jeśli jesteśmy na podstronie ze zmiennymi w adresie) lub "?" (jeśli jesteśmy na stronie głównej lub stronie bez zmiennych w adresie - w tym przypadku index.php).

W poniższym kodzie jest też uwzględnione to, że po wykonaniu sortowania na podstronie z posortowaną już zawartością tabeli w polu SELECT jest wybrana ta opcja, która posłużyła nam do sortowania i wczytania aktualnej strony.

Ważne jest, aby w linku, który jest wartością (value) każdego pola OPTION, wartość zmiennej sort każdej opcji do wybrania, była zgodna z nazwą kolumny z późniejszego zapytania SQL.

  1. <select onchange="location = this.value;">
  2. <?php
  3. if(($_SERVER['REQUEST_URI'] == "/") OR ($_SERVER['REQUEST_URI'] == "/index.php")) $char="http://twojastrona.pl/index.php?";
  4. elseif($_GET['sort']) {
  5.  
  6. $char = "".$_SERVER['REQUEST_URI']."";
  7. $char = "http://twojastrona.pl/".str_replace("/","",substr($char, 0, strpos($char, "sort")))."";
  8.  
  9. }
  10. else $char = "http://twojastrona.pl".$_SERVER['REQUEST_URI']."&";
  11.  
  12. $opcje = '
  13. <option value="'.$_SERVER['REQUEST_URI'].'">-----------</option>
  14. <option value="'.$char.'sort=od&order=ASC">Wolny od (rosnąco)</option>
  15. <option value="'.$char.'sort=od&order=DESC">Wolny od (malejąco)</option>
  16. <option value="'.$char.'sort=do&order=ASC">Wolny do (rosnąco)</option>
  17. <option value="'.$char.'sort=do&order=DESC">Wolny do (malejąco)</option>
  18. <option value="'.$char.'sort=zmia&order=ASC">Załadunek (miasto) (rosnąco)</option>
  19. <option value="'.$char.'sort=zmia&order=DESC">Załadunek (miasto) (malejąco)</option>
  20. <option value="'.$char.'sort=zpan&order=ASC">Załadunek (państwo) (rosnąco)</option>
  21. <option value="'.$char.'sort=zpan&order=DESC">Załadunek (państwo) (malejąco)</option>
  22. <option value="'.$char.'sort=rmia&order=ASC">Rozładunek (miasto) (rosnąco)</option>
  23. <option value="'.$char.'sort=rmia&order=DESC">Rozładunek (miasto) (malejąco)</option>
  24. <option value="'.$char.'sort=rpan&order=ASC">Rozładunek (państwo) (rosnąco)</option>
  25. <option value="'.$char.'sort=rpan&order=DESC">Rozładunek (państwo) (malejąco)</option>
  26. <option value="'.$char.'sort=rodzaj_pojazdu&order=ASC">Rodzaj (rosnąco)</option>
  27. <option value="'.$char.'sort=rodzaj_pojazdu&order=DESC">Rodzaj (malejąco)</option>
  28. <option value="'.$char.'sort=zgloszone&order=ASC">Zgłoszone (rosnąco)</option>
  29. <option value="'.$char.'sort=zgloszone&order=DESC">Zgłoszone (malejąco)</option>
  30. <option value="'.$char.'sort=cena&order=ASC">Cena (rosnąco)</option>
  31. <option value="'.$char.'sort=cena&order=DESC">Cena (malejąco)</option>';
  32.  
  33. if(isset($_GET['sort'])) {
  34.  
  35. $opcje = str_replace('value="'.$char.'sort='.$_GET['sort'].'&order='.$_GET['order'].'','selected value="'.$char.'sort='.$_GET['sort'].'&order='.$_GET['order'].'',$opcje);
  36.  
  37. }
  38. ?>
  39. </select>

Teraz wystarczy przed zapytaniem MySQL wstawić poniższy kod, aby zapytanie SQL pobrało dane odpowiednio zgodne z tym co wybierzemy w polu SELECT.

  1. <?php
  2. // sortowanie
  3. if(isset($_GET['sort']) and isset($_GET['order'])) {
  4.  
  5. $sort = $_GET['sort'];
  6. $order = $_GET['order'];
  7.  
  8. } else {
  9.  
  10. $sort = "{twoja_domyślna_opcja}";
  11. $order = "DESC";
  12. }
  13. ?>

Zapytanie MySQL

  1. SELECT
  2.  
  3. wp.*,
  4. z.panstwo AS zpan, z.miasto AS zmia, z.kod AS zkod, z.od,
  5. r.panstwo AS rpan, r.miasto AS rmia, r.kod AS rkod, r.do,
  6. p.rodzaj_pojazdu, o.*
  7.  
  8. FROM wolne_pojazdy AS wp
  9. JOIN zaladunek AS z ON z.id_zaladunek=wp.id_zaladunku
  10. JOIN rozladunek AS r ON r.id_rozladunek=wp.id_zaladunku
  11. JOIN pojazd AS p ON p.id_pojazd=wp.id_pojazdu
  12. JOIN oplaty AS o ON o.id_oplata=wp.id_oplaty
  13.  
  14. ORDER BY $sort $order LIMIT $od, 30


Kod PHP
  1. <?php
  2.  
  3. $rezultat = "(...)"; // tutaj powyższe zapytanie
  4. $wynik = mysql_query($rezultat) or die(mysql_error());
  5.  
  6. while($row = mysql_fetch_array($wynik))
  7. {
  8.  
  9. // flagi
  10.  
  11. $flaga = $row['zpan'];
  12. $flaga = strtr($flaga, 'ĘÓĄŚŁŻŹĆŃęóąśłżźń', 'EOASLZZCNeoaslzzcn');
  13. $flaga_sciezka = "grafika/flagi/$flaga.gif";
  14. if (file_exists($flaga_sciezka)) { $flaga_plik = "<img title='".$row['zpan']."' alt='".$row['zpan']."' src='grafika/flagi/$flaga.gif' />"; }
  15.  
  16. $flaga2 = $row['rpan'];
  17. $flaga2 = strtr($flaga2, 'ĘÓĄŚŁŻŹĆŃęóąśłżźń', 'EOASLZZCNeoaslzzcn');
  18. $flaga_sciezka2 = "grafika/flagi/$flaga2.gif";
  19. if (file_exists($flaga_sciezka2)) { $flaga_plik2 = "<img title='".$row['rpan']."' alt='".$row['rpan']."' src='grafika/flagi/$flaga2.gif' />"; }
  20.  
  21. // cena
  22.  
  23. $cena_rozbij = explode(".", $row['cena']);
  24. if($cena_rozbij[1]==00) {
  25. $cena = $cena_rozbij[0];
  26. } else {
  27. $cena=$row['cena'];
  28. }
  29.  
  30. ?>
  31.  
  32. <tr <? if (($odlicz%2)==0) { echo "bgcolor='#eeeeee'"; } else { echo "bgcolor='#e7e7e7'"; }?>>
  33. <td class="tabela_komorka center" width="90">
  34. <div class="table mauto">
  35. <div><i class="icon-truck text-white" style="font-size: 16px"></i></div>
  36. <div>
  37. <div><strong class="dater bg-darkgrey text-white"><? echo date("d.m.Y", $row['od']); ?></strong></div>
  38. <div><strong class="dater bg-head text-white"><? echo date("d.m.Y", $row['do']); ?></strong></div>
  39. </div>
  40. </div>
  41. </td>
  42. <td><?php echo $flaga_plik; ?><br /><?php echo $row['zpan']; ?><br /><?php echo ucwords($row['zmia']); ?><br /><?php echo $row['zkod']; ?></td>
  43. <td><?php echo $flaga_plik2; ?><br /><?php echo $row['rpan']; ?><br /><?php echo ucwords($row['rmia']); ?><br /><?php echo $row['rkod']; ?></td>
  44. <td><?php echo $row['rodzaj_pojazdu']; ?></td>
  45. <td><strong><? echo $row['data_zgloszenia']; ?></strong><br /><? echo $row['godzina_zgloszenia']; ?></td>
  46. <td><? if($row['cena_do_uzgodnienia']==1) { echo "<strong>Cena:</strong><br>Do uzgodnienia<br><strong>Płatność:</strong><br>".$row['nazwa_rodzaju_platnosci'].""; } else { echo "<strong>".$cena." ".$row['skrot_waluty']."</strong><br>za<br><strong>".$row['za_co_oplata_nazwa']."</strong>"; }?></td>
  47. <td><a href="index.php?k=wolne-pojazdy&szczegoly=<? echo $row['id_wolne_pojazdy']; ?>">Zobacz</a></td></tr>
  48.  
  49. <?
  50.  
  51. }
  52.  
  53. ?>


PS. Jeśli chcesz mi dodać punkta klikając w przycisk POMÓGŁ, to zanim to zrobisz, koniecznie podziękuj w identyczny sposób użytkownikowi
Greg0
, który przyczynił się w kluczowy sposób do rozwiązania problemu.

Dzięki wszystkim za miłe chęci i za realną pomoc Greg0'wi
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.