Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wybranie danych z dwóch tabel
Forum PHP.pl > Forum > Bazy danych > MySQL
jg44
Witam,
mam dwie następujące tabele: `uzytkownicy`(`ID`,`nazwa_uzytkownika`) oraz `mecze`(`gracz1`,`gracz2`).
Powiązane są kluczami obcymi:
  1. FOREIGN KEY(`gracz1`) REFERENCES `uzytkownicy`(`ID`),
  2. FOREIGN KEY(`gracz2`) REFERENCES `uzytkownicy`(`ID`)

W tabeli `mecze` w kolumnach `gracz1` oraz `gracz2` przechowywane są ID zawodników. Problem polega na tym, że chcę wybrać wszystkie mecze zalogowanego użytkownika (czyli takie rekordy, gdzie zalogowany użytkownik jest zapisany w polu `gracz1` lub `gracz2`). Znane jest zarówno ID tego zalogowanego użytkownika (pod zmienną $this->id) jak i nazwa (zmienna $this->user_name).
Próbowałem w taki sposób, jednak to bardzo źle działa, bo co prawda wyświetla mecze zalogowanego użytkownika, ale wszędzie wrzuca jego nazwę:
  1. function printGames()
  2. {
  3. $r = mysql_query("SELECT * FROM mecze,uzytkownicy
  4. WHERE mecze.gracz1 = uzytkownicy.ID AND mecze.gracz1='$this->id' OR mecze.gracz2 = uzytkownicy.ID AND mecze.gracz2='$this->id'")or die(mysql_error());
  5. if(mysql_num_rows($r) != 0)
  6. {
  7. echo "<table>";
  8. echo "<tr><td><strong>Zawodnik 1</strong></td>
  9. <td><strong>Wynik zawodnika 1</strong></td>
  10. <td></td>
  11. <td><strong>Wynik zawodnika 2</strong></td>
  12. <td><strong>Zawodnik 2</strong></td>
  13. <td><strong>Mecz rozegrano</strong></td></tr>";
  14. while($l = mysql_fetch_array($r))
  15. {
  16. echo "<tr><td>" .$l['nazwa_uzytkownika']. "</td>";
  17. echo "<td><center>" .$l['wynik_gracz1']. "</center></td>";
  18. echo "<td><center>" .$l['wynik_gracz2']. "</center></td>";
  19. echo "<td>" .$l['nazwa_uzytkownika']. "</td>";
  20. }
  21. echo "</table>";
  22. }
  23. else
  24. {
  25. echo "<h5 class=\"correct\">Nie rozegrałeś(-aś) jeszcze żadnego meczu.</h5>";
  26. }
  27. }

Przykładowo, załóżmy, że zalogownym użytkownikiem jest Ewa Szańska. Powyższy fragment powinien zwrócić tabelę wynikową:
Kod
zawodnik1          | wynik_zawodnik1 | wynik_zawodnik2 | zawodnik2
Ewa Szańska                        3   0                 Jurek KIler
Stefan Siarzewski                  3   2                 Ewa Szańska

a zamiast tego zwraca:
Kod
zawodnik1          | wynik_zawodnik1 | wynik_zawodnik2 | zawodnik2
Ewa Szańska                        3   0                 Ewa Szańska
Ewa Szańska                        3   2                 Ewa Szańska


Błąd prawdopodobnie leży w linii 19 metody drukującej dane (jak widać dwa razy drukuję $l['nazwa_uzytkownika'] i dlatego nadpisuje mi pozostałe nazwiska). Jak sobie z tym poradzić?
____________________________________________
Albo inaczej:
jeśli zmodyfikuję pętlę wybierającą na następującą:
  1. while($l = mysql_fetch_array($r))
  2. {
  3. echo "<tr><td>" .$l['gracz1']. "</td>";
  4. echo "<td><center>" .$l['wynik_gracz1']. "</center></td>";
  5. echo "<td><center>" .$l['wynik_gracz2']. "</center></td>";
  6. echo "<td>" .$l['gracz2']. "</td>";
  7. }

to działa dobrze, ale zamiast nazwy użytkownika drukuje jego ID. Jak zrobić, aby zamiast ID drukowana była nazwa użytkownika?
Z góry dziękuję za pomoc.
mortus
Może lepszym rozwiązaniem będzie złączenie:
  1. SELECT `u1`.`nazwa_uzytkownika` `zawodnik1`, `m`.`wynik_gracz1`, `m`.`wynik_gracz2`, `u2`.`nazwa_uzytkownika` `zawodnik2` FROM `mecze` `m`
  2. LEFT JOIN `uzytkownicy` `u1` ON (`u1`.`ID` = `m`.`gracz1` AND `m`.`gracz1` = {$this->id})
  3. LEFT JOIN `uzytkownicy` `u2` ON (`u2`.`ID` = `m`.`gracz2` AND `m`.`gracz2` = {$this->id})

Chyba jakoś tak, choć dzisiaj nie mam najlepszego myślenia.
jg44
Raczej tak, złączenie będzie dobrym pomysłem. Jednak Twoje zapytanie działa nie do końca - zwraca wszystkie rekordy z tabeli `mecze` (także te, w których zalogowany gracz wcale nie grał), drugi problem jest taki, że nie jest wyświetlany przeciwnik. Dokładniej wygląda to tak:
Kod
gracz1      | wynik_gracz1 | wynik_gracz2 | gracz2
                         3   0
                         3   2
Ewa Szańska              3   0
                         2   1              Ewa Szańska

W tabeli `mecze` mam łącznie 4 rekordy. Zakładamy, że Ewa Szańska jest zalogowana. W pierwszych meczach nie grała, a zostały wyświetlone (bez nazwisk). No i tam, gdzie grała, nazwisk rywali tównież nie ma...
EDIT: w pierwszym poście zrobiłem lieterówkę - podałem, że w tabeli `mecze` są pola `zawodnik1` i `zawodnik2` - tak nie jest, te pola nazywają się `gracz1` i `gracz2`.
mortus
Jak patrzę na to zapytanie, to nie dziwię się, że zwraca nie to co trzeba. Poprawione:
  1. SELECT `u1`.`nazwa_uzytkownika` `zawodnik1`, `m`.`wynik_gracz1`, `m`.`wynik_gracz2`, `u2`.`nazwa_uzytkownika` `zawodnik2` FROM `mecze` `m`
  2. LEFT JOIN `uzytkownicy` `u1` ON (`u1`.`ID` = `m`.`gracz1`)
  3. LEFT JOIN `uzytkownicy` `u2` ON (`u2`.`ID` = `m`.`gracz2`)
  4. WHERE `m`.`gracz1` = {$this->id} OR `m`.`gracz2` = {$this->id}


zawodnik1 i zawodnik2 w powyższym zapytaniu, to aliasy dla pierwszej i drugiej nazwy użytkownika, a nie kolumny z tabeli mecze.
pmir13
Problem leży w zapytaniu, właściwe byłoby
  1. SELECT u1.nazwa_uzytkownika, m.wynik1, m.wynik2, u2.nazwa_uzytkownika
  2. FROM mecze m
  3. JOIN uzytkownicy u1 ON m.gracz1=u1.ID
  4. JOIN uzytkownicy u2 ON m.gracz2=u2.ID
  5. WHERE m.gracz1={$this->id} OR m.gracz2={$this->id}

Postaraj się też dokładnie podawać strukturę tabel, zgaduję jedynie że w tabeli mecze są jeszcze kolumny wynik1 i wynik2 i być może jakieś inne, które na pozór mogą być nieistotne dla tego problemu, ale przykładowo jeśli nie zapisujesz daty meczu i nie chcesz po niej sortować to mógłbyś uniknąć używania OR i mieć dwa prostsze i sumarycznie dużo szybsze zapytania z podanym użytkownikiem najpierw na pierwszym a potem drugim miejscu. Nie czepiam się, po prostu precyzyjne dane oszczędzają sporo czasu i myślenia komuś, kto chce odpowiedzieć.
jg44
Super, bardzo Ci dziękuję mortus! smile.gif
pmir13, masz rację, chciałem się wysłowić, żeby wszystko było w miarę jasne i niedokładnie podałem strukturę tabeli. Odgadłeś precyzyjnie, istnieją jeszcze kolumny `wynik_gracz1` oraz `wynik_gracz2`.
Niemniej problem został rozwiązany. smile.gif
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.