Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Sortowanie danych w tabeli
Forum PHP.pl > Forum > Przedszkole
maniek2512
Otóż mam oto taki kod:

  1. <table class="sortable" border="1" align="left" width="100%" >
  2. <!-- Table Header -->
  3. <thead>
  4.  
  5. <tr>
  6. <th background='tlo.png'>L.P.</th>
  7. <th background='tlo.png'>Nick</th>
  8. <th background='tlo.png'>Marka</th>
  9. <th background='tlo.png'>Model</th>
  10. <th background='tlo.png'>Czas</th>
  11. <th background='tlo.png'>Tryb</th>
  12. </tr>
  13.  
  14. </thead>
  15.  
  16. <!-- Tabel body-->
  17. <tbody>
  18.  
  19.  
  20.  
  21. <?php
  22. $lp= 1;
  23. $trasa = $_GET['trasa'];
  24. $tryb = $_GET['tryb'];
  25. $shard = $_GET['shard'];
  26.  
  27.  
  28.  
  29. $sql_conn = mysql_connect('########', '#####_admin', '#######');
  30. mysql_select_db('nfswinfo_1');
  31.  
  32. $result3 = mysql_query("SELECT nick FROM CHICANE");
  33.  
  34. $wynik = '';
  35.  
  36. while ($row3 = mysql_fetch_array($result3, MYSQL_ASSOC)){
  37.  
  38. $user = $row3["nick"];
  39.  
  40.  
  41. $result = mysql_query("SELECT * FROM single$trasa WHERE nick='$user' ORDER BY czas ASC");
  42. $row2 = mysql_fetch_array($result);
  43.  
  44. $czas2 = $row2["czas"];
  45.  
  46. $result1 = mysql_query("SELECT * FROM multi$trasa WHERE nick='$user' ORDER BY czas ASC");
  47. $row1 = mysql_fetch_array($result1);
  48.  
  49. $czas1 = $row1["czas"];
  50.  
  51.  
  52. if (empty($czas2)){
  53.  
  54. $czas2 = '0:00:00.000';
  55. }
  56.  
  57. if (empty($czas1)){
  58.  
  59. $czas1 = '0:00:00.000';
  60. }
  61.  
  62.  
  63. if ($czas2 < $czas1){
  64.  
  65. $wynik .= '<tr align="center"><td>'.$lp++.'</td><td>'.$row1["nick"].'</td><td>'.$row1["marka"].'</td><td>'.$row1["model"].'</td><td>'.$czas1.'</td><td>Multiplayer</td></tr>';
  66. }
  67.  
  68. elseif ($czas2 > $czas1){
  69.  
  70. $wynik .= '<tr align="center"><td>'.$lp++.'</td><td>'.$row2["nick"].'</td><td>'.$row2["marka"].'</td><td>'.$row2["model"].'</td><td>'.$czas2.'</td><td>Singleplayer</td></tr>';
  71. }
  72.  
  73. else { }
  74.  
  75.  
  76. }
  77.  
  78.  
  79. echo $wynik;
  80.  
  81. ?>
  82.  
  83. </tbody> </table>
  84.  
  85.  
  86.  
  87.  



Co zrobić aby wynik był posortowany względem czasu od najkrótszego do najdłuższego?

Obecnie skrypt zwraca wynik:

L.P. Nick Marka Model Czas Tryb
1 MANIEK2512PL PAGANI ZONDA CINQUE 0:01:19.817 Singleplayer
2 JOERG1966 MCLAREN F1 0:01:13.800 Multiplayer
3 RYBECKI0902 PAGANI ZONDA CINQUE 0:01:23.075 Singleplayer
4 DELECTAMENTI PAGANI ZONDA CINQUE 0:01:12.861 Singleplayer
5 BLACKSHADOW849 PAGANI ZONDA CINQUE 0:01:21.805 Singleplayer
Michael2318
Czas musisz mieć w formacie timestamp i wtedy nie ma problemu - order by time desc/asc.
Michasko
W polu typu timestamp przechowujemy datę i czas, a tutaj masz coś, co wygląda jak np. czas wykonania okrążenia na jakichś wyścigach smile.gif
maniek2512
Cytat(Michasko @ 27.01.2013, 14:41:51 ) *
W polu typu timestamp przechowujemy datę i czas, a tutaj masz coś, co wygląda jak np. czas wykonania okrążenia na jakichś wyścigach smile.gif



Bo tak właśnie jest, jest to czas ukończenia wyścigu. Więc sposób Michaela2318 nie będzie działał?
kristaps
Pobierasz wyniki z dwóch tabel, następnie je porównujesz i tworzysz tabelkę. Jednym z rozwiązań będzie stworzenie tablicy dwuwymiarowej (zmienna $wynik), a następnie array_multisort.
Michasko
Nie bardzo. Na Twoim miejscu czas ukończenia przechowywałbym w milisekundach w bazie, a dopiero potem (przy wyświetlaniu) konwertował na czas w Twoim formacie.
Funkcja znaleziona na StackOverflow:
  1. function formatMilliseconds($milliseconds) {
  2. $seconds = floor($milliseconds / 1000);
  3. $minutes = floor($seconds / 60);
  4. $hours = floor($minutes / 60);
  5. $milliseconds = $milliseconds % 1000;
  6. $seconds = $seconds % 60;
  7. $minutes = $minutes % 60;
  8.  
  9.  
  10.  
  11. $format = '%u:%02u:%02u.%03u';
  12. $time = sprintf($format, $hours, $minutes, $seconds, $milliseconds);
  13. return $time;
  14. }
maniek2512
Cytat(Michasko @ 27.01.2013, 15:59:47 ) *
Nie bardzo. Na Twoim miejscu czas ukończenia przechowywałbym w milisekundach w bazie, a dopiero potem (przy wyświetlaniu) konwertował na czas w Twoim formacie.
Funkcja znaleziona na StackOverflow:
  1. function formatMilliseconds($milliseconds) {
  2. $seconds = floor($milliseconds / 1000);
  3. $minutes = floor($seconds / 60);
  4. $hours = floor($minutes / 60);
  5. $milliseconds = $milliseconds % 1000;
  6. $seconds = $seconds % 60;
  7. $minutes = $minutes % 60;
  8.  
  9.  
  10.  
  11. $format = '%u:%02u:%02u.%03u';
  12. $time = sprintf($format, $hours, $minutes, $seconds, $milliseconds);
  13. return $time;
  14. }


Ten sposób odpada ponieważ przy update tabeli musiałbym konwertować czas na milisekundy, a następnie jeszcze raz je konwertować tak jak napisałeś. Spróbuję sposobu z tablicą dwuwymiarową.
kristaps
Ten sposób jest bardzo dobry i wskazany jeżeli chodzi o przechowywanie danych. No ale w ogóle nie rozwiązuje problemu z posortowanie wybranych rekordów 2 tabel.

Pobierasz, porównujesz, wybierasz jeden rekord, następnie zapisujesz do zmiennej, pętla leci dalej i dopisuje. Także stwórz tablicę, a następnie sortuj jej wyniki. No chyba, że ktoś ma inny pomysł - pamiętając, że nie można tutaj sortować danych po czasie.

E: Tablicę wrzucasz oczywiście do pętli - przykład:
  1. $tablica = array();
  2. while ($row = mysql_fetch_array($SQL)) {
  3.  
  4. $tablica[] = array($row['czas'], $row['login']);
  5.  
  6. }

Następnie na niej operujesz.
abort
Po chwilowym zastanowieniu się dochodzę do wniosku, że dla wygenerowania topilsty 10 pozycji potrzebujemy:
1. Pobrać z bazy 10 najlepszych czasów z trybu singleplayer i zapisać do tablicy $top, jednocześnie dodając kolumnę "tryb" o wartości "singleplayer"
2. Pobrać z bazy 10 najlepszych czasów z trybu multiplayer i zapisać do tablicy $top, jednocześnie dodając kolumnę "tryb" o wartości "multiplayer"
3. posortować tablicę za pomocą uksort (polecam doczytać w manualu)
4. wyświetlić 10 pierwszych rekordów

Koniec.

A tak w ogóle, to dlaczego nie pomyślisz i nie zrzucisz całej roboty na bazę zamiast tak utrudniać sobie życie?
Gdybyś wszystkie wyścigi miał w jednej tabeli, z dodatkowym polem "tryb", w którym miałbyś informację o tym, czy to było "single", czy "multi", to toplistę wyciągasz jednym zapytaniem smile.gif
Musisz tylko przeorganizować bazę - wszystkie wyniki wrzucić do JEDNEJ tabeli i dodać jedno pole - dokładnie to samo, co przedstawiłem w punktach 1 i 2.
Oczywiście nie przeszkadza to w wyciąganiu N najlepszych wyników dla trybu np. singleplayer - załatawia to jedna klauzula "WHERE" w zapytaniu.

P.S.
CZASY DA SIĘ posortować - jeśli format się nie zmienia, to czas JEST sortowalny (klauzula "ORDER BY")
kristaps
Tak, jeżeli przeorganizuje bazę danych, to jest to najbardziej wykonalne. Pomagałem przy poprzednim temacie i mniej więcej wiem jak to wygląda. Maniek2512 porównuje czas graczy z X trasy, dla trybu single i multi. Załóżmy, że ma takie tabele:

Singleplayer trasa #21 (login, czas)
Cytat
MANIEK2512PL -02.00
JOERG1966-01.45
RYBECKI0902-02.02
BLACKSHADOW849-01.03

Multiplayer trasa #21 (login, czas)
Cytat
MANIEK2512PL -01.50
BLACKSHADOW849-00.99

W efekcie dla danej trasy (których jest załóżmy 20) nie wszyscy użytkownicy rozegrali oba tryby i otrzymamy:
Cytat
MANIEK2512PL -01.50
BLACKSHADOW849-00.99
JOERG1966-01.45
RYBECKI0902-02.02


Także wyciągnięcie top 10 nic nie da. Wyjściem jest właśnie tablica po porównaniu czasów z obu trybów rozgrywki dla danego gracza.
abort
Cytat(kristaps @ 27.01.2013, 20:52:15 ) *
Także wyciągnięcie top 10 nic nie da. Wyjściem jest właśnie tablica po porównaniu czasów z obu trybów rozgrywki dla danego gracza.

A, ok - na Twoim przykładzie widać doskonale to, czego nie widać na przykładzie autora wątku. Zgadza się, nie jest to tabela najlepszych rezultatów na torze, tylko tabela najlepszych rezultatów graczy na torze.
Jak dla mnie najlepiej przeorganizować bazę - będzie prościej w kodzie, a problem autora być może da się sprowadzić do jednej kwerendy bazy (ale tu już niech pomogą lepsi)
kristaps
To bodajże z NFS'da, ciekawe swoją drogą jak wygląda pobieranie wyników i aktualizowanie bazy w obu trybach (głównie single). Także trudno powiedzieć czy jest w ogóle możliwość przebudowy bazy - być może cały mechanizm na to nie pozwala. Jak Maniek zastosuje się do rady z tablicą w pętli to powinien bez problemu posegregować wyniki.
maniek2512
Napisałem coś takiego:
  1.  
  2. <?php
  3. $lp= 1;
  4. $trasa = $_GET['trasa'];
  5. $tryb = $_GET['tryb'];
  6. $shard = $_GET['shard'];
  7.  
  8.  
  9.  
  10. $sql_conn = mysql_connect('**********', '********_admin', '**********');
  11. mysql_select_db('nfswinfo_1');
  12.  
  13. $result3 = mysql_query("SELECT nick FROM CHICANE");
  14.  
  15. $tablica = array();
  16. $wynik = '';
  17.  
  18. while ($row3 = mysql_fetch_array($result3, MYSQL_ASSOC)){
  19.  
  20. $user = $row3["nick"];
  21.  
  22.  
  23. $result = mysql_query("SELECT * FROM single$trasa WHERE nick='$user' ORDER BY czas ASC");
  24. $row2 = mysql_fetch_array($result);
  25.  
  26. $czas2 = $row2["czas"];
  27.  
  28. $result1 = mysql_query("SELECT * FROM multi$trasa WHERE nick='$user' ORDER BY czas ASC");
  29. $row1 = mysql_fetch_array($result1);
  30.  
  31. $czas1 = $row1["czas"];
  32.  
  33.  
  34. if (empty($czas2)){
  35.  
  36. $czas2 = '9:99:99.999';
  37. }
  38.  
  39. if (empty($czas1)){
  40.  
  41. $czas1 = '9:99:99.999';
  42. }
  43.  
  44.  
  45. if ($czas2 > $czas1){
  46.  
  47. $wynik .= '<tr align="center"><td>'.$lp++.'</td><td>'.$row1["nick"].'</td><td>'.$row1["marka"].'</td><td>'.$row1["model"].'</td><td>'.$czas1.'</td><td>Multiplayer</td></tr>';
  48.  
  49. $czas = $czas1;
  50. $nick = $row1["nick"];
  51. $marka = $row1["marka"];
  52. $model = $row1["model"];
  53. $tryb = "Multiplayer";
  54. }
  55.  
  56. elseif ($czas2 < $czas1){
  57.  
  58. $wynik .= '<tr align="center"><td>'.$lp++.'</td><td>'.$row2["nick"].'</td><td>'.$row2["marka"].'</td><td>'.$row2["model"].'</td><td>'.$czas2.'</td><td>Singleplayer</td></tr>';
  59.  
  60. $czas = $czas2;
  61. $nick = $row2["nick"];
  62. $marka = $row2["marka"];
  63. $model = $row2["model"];
  64. $tryb = "Singleplayer";
  65. }
  66.  
  67. else { }
  68.  
  69. $tablica[] = array($czas, $nick, $marka, $model, $tryb);
  70. array_multisort($tablica, SORT_ASC);
  71.  
  72. }
  73.  
  74. echo $tablica[1][0];
  75.  
  76. echo "<pre>"; print_r($tablica); echo "</pre>";
  77.  
  78.  
  79. ?>
  80.  
  81.  
  82. </tbody> </table>
  83.  
  84.  


lecz mam problem z wyświetleniem danych.
Tablica wygląda w ten sposób:

Array
(
[0] => Array
(
[0] => 0:01:09.435
[1] => JOERG1966
[2] => MCLAREN
[3] => F1
[4] => Singleplayer
)

[1] => Array
(
[0] => 0:01:12.861
[1] => DELECTAMENTI
[2] => PAGANI
[3] => ZONDA CINQUE
[4] => Singleplayer
)

[2] => Array
(
[0] => 0:01:16.675
[1] => RYBECKI0902
[2] => PAGANI
[3] => ZONDA CINQUE
[4] => Multiplayer
)
(...)
)


Wiem, że trzeba je wyświetlić tak:

  1. echo $tablica[0][1]

itd. Lecz czy można to wstawić do tabeli tak jak miałem to wcześniej, czyli coś w tym stylu (+ ewentualnie jak to zrobić):

  1. <table border="1" align="left" width="100%" >
  2. <!-- Table Header -->
  3. <thead>
  4.  
  5. <tr>
  6. <th background='tlo.png'>L.P.</th>
  7. <th background='tlo.png'>Nick</th>
  8. <th background='tlo.png'>Marka</th>
  9. <th background='tlo.png'>Model</th>
  10. <th background='tlo.png'>Czas</th>
  11. <th background='tlo.png'>Tryb</th>
  12. </tr>
  13.  
  14. </thead>
  15.  
  16. <!-- Tabel body-->
  17. <tbody>
  18. <?php
  19. (...)
  20. $playertime = '<td>' . $tablica['czas'] . '</td>';
  21. $playername = '<td>' . $tablica['nick'] . '</td>';
  22. $playermake = '<td>' . $tablica['marka'] . '</td>';
  23. $playercar = '<td>' . $tablica['model'] . '</td>';
  24. $playermode = '<td>' . $tablica['tryb'] . '</td>';
  25. $playerrank = '<td>' . $lp++ . '</td>';
  26.  
  27.  
  28. echo "<tr align='center'>$playerrank $playername $playertime $playermake $playercar $playermode</tr>";
  29.  
  30. ?>
  31.  
  32. </tbody> </table>
  33.  
  34.  
  35.  
  36.  
  37.  
  38. <table class="sortable" border="1" align="left" width="100%" >
  39. <!-- Table Header -->
  40. <thead>
  41.  
  42. <tr>
  43. <th background='tlo.png'>L.P.</th>
  44. <th background='tlo.png'>Nick</th>
  45. <th background='tlo.png'>Marka</th>
  46. <th background='tlo.png'>Model</th>
  47. <th background='tlo.png'>Czas</th>
  48. <th background='tlo.png'>Tryb</th>
  49. </tr>
  50.  
  51. </thead>
  52.  
  53. <!-- Tabel body-->
  54. <tbody>
  55.  
  56.  
kristaps
Po pierwsze wyrzuć
  1. array_multisort($tablica, SORT_ASC);
z głównej pętli. Aktualnie sortujesz tablice z każdym wykonaniem pętli - a kompletna jest przecież dopiero po ostatnim pobraniu użytkownika z tabeli chicane. Otrzymujesz dobry wynik, ale zmniejszasz wydajność skryptu. Co do pytania, to żeby wyświetlić całą posortowaną tablicę, musisz użyć kolejnej pętli (poza główną pętlą).

Tym razem bez gotowca (znam każdą linię Twojego skryptu wink.gif). Spróbuj sam na podstawie tego przykładu:
  1. <?php
  2. $kraje = Array(
  3. 'Europa' => array('Polska', 'Anglia', 'Litwa', 'Francja'),
  4. 'Afryka' => array('Tunezja', 'Egipt', 'RPA', 'Etiopia'),
  5. 'Azja' => array('Chiny', 'Mongolia', 'Japonia', 'Kazachstan')
  6. );
  7.  
  8. echo '<table>';
  9.  
  10. foreach ( $kraje as $kontynent => $kraj )
  11. {
  12. echo '<tr><td width="20%"><b>' . $kontynent . '</b></td>';
  13.  
  14. for ( $i = 0; $i < count($kraj); $i++ )
  15. {
  16. echo '<td width="20%">' . $kraj[$i] . '</td>';
  17. }
  18.  
  19. echo '</tr>';
  20. }
  21.  
  22. echo '</table>';
  23.  
  24. ?>

Tablica jest nieco inna, ale jak wyświetlisz wynik tego skryptu i porównasz z swoją to powinieneś zobaczyć zależność. Jak coś to pytaj ewentualnie doczytaj o foreach i tablicach dwuwymiarowych.
maniek2512
Dzięki wielkie, zrobiłem tak i wszystko gra:

  1. (...)
  2. $tablica[] = array($nick, $marka, $model, $czas, $tryb);
  3.  
  4.  
  5. }
  6. foreach ($tablica as $key => $row5) {
  7. $time[$key] = $row5['3'];
  8.  
  9. }
  10. array_multisort($time, SORT_ASC, $tablica);
  11.  
  12.  
  13. echo "<pre>"; print_r($tablica); echo "</pre>";
  14.  
  15.  
  16.  
  17. foreach ( $tablica as $pozycja => $gracz )
  18. {
  19. $lp=1;
  20. $pozycja1=$pozycja+$lp ;
  21. echo '<tr align="center"><td><b>' . $pozycja1 . '</b></td>';
  22.  
  23. for ( $i = 0; $i < count($gracz); $i++ )
  24. {
  25. echo '<td>' . $gracz[$i] . '</td>';
  26. }
  27.  
  28. echo '</tr>';
  29. }
  30.  
kristaps
  1. foreach ($tablica as $key => $row5) {
  2. $time[$key] = $row5['3'];
  3.  
  4. }
  5. array_multisort($time, SORT_ASC, $tablica);

Wykonujesz pętlę na tablicy, a później ją sortujesz. Zmień kolejność, najpierw array_multisort, później foreach.

Edit: Chociaż jest ok, do tej pętli nie musisz chyba sortować tablicy.

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.