Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Nietypowe sortowanie
Forum PHP.pl > Forum > PHP
emil1702
Witajcie

Moja jedna z tabel wygląda wygląda następująco

nazwa: biegi

idbiegu z1 z2 z3 z4 cz1 cz2 cz3 cz4

z1, z2, z3, z4 - to id zawodnika, natomiast cz1, cz2, cz3, cz4 - to czasy zawodników.

Chciałbym, aby wszystko zostało posortowane według czasów, a więc.

z2, czas 44:44
z1, czas 45:44
z3, czas 45:45
z4, czas 60:00

dodatkowo, aby czasy zawodnika 1 były zawsze oznaczone kolorem czerwonym, zaw 2 niebieskim itd.


Jakie zapytanie do bazy mysql pomoże mi to najłatwiej wykonać?
Crozin
Masz nieprawidłową strukturę tabeli. Powinieneś mieć dwie tabele: 1) biegi (id), 2) uczestnicy (id, id_biegu, id_zawodnika, czas). Mając normalną strukturę danych, będziesz mógł to bez problemu posortować i wyświetlić.
emil1702
Dziękuje za podpowiedź, zrobie tak jak mówisz. Pozdrawiam smile.gif
lukaskolista
struktura tabeli jest prawidlowa - jezeli w biegu moze brac udzial 4 zawodnikow (gra zuzlowa) i nigdy nie bedzie moglo byc ich wiecej
phpion
@lukaskolista:
Nie jest prawidłowa. Czy jeśli chciałbyś przechowywać statystyki przebiegniętych kilometrów przez piłkarzy (akurat na czasie) to stworzyłbyś 22 kolumny? W sumie nawet to byłoby mało - w międzyczasie wchodzą jeszcze przecież rezerwowi, więc musiałbyś przewidzieć 28 kolumn smile.gif
d3ut3r
Cytat
struktura tabeli jest prawidlowa - jezeli w biegu moze brac udzial 4 zawodnikow (gra zuzlowa) i nigdy nie bedzie moglo byc ich wiecej


Ja bym się z tym nie zgodził, trzeba poczytać o normalizacji baz danych i ogólnie o projektowaniu struktur, najkrócej tworząc tabelę biegi przechowujesz dane dotyczące biegu (dystans,nazwa trasy,data rozpoczęcia itp.) czas zawodnika nie jest daną która do tego kryterium pasuje . Właśnie dlatego są to relacyjne bazy danych aby z tych relacji skorzystać.
lukaskolista
Tak tak, mialem teorie na studiach... Chyba nie powiecie mi, ze lepiej miec 4x wiecej rekordow do przeszukiwania. Czasami trzeba zrobic cos inaczej, niz mowi teoria, aby bylo to bardziej optymalne. Widzialem skrypt oparty na takiej strukturze (wlasnie gra zuzlowa) i wlasnie taka struktura spelnila swoje zadanie.

phpion:
sa tabele po 100 kolumn i jakos to dziala smile.gif
Cytat
W sumie nawet to byłoby mało - w międzyczasie wchodzą jeszcze przecież rezerwowi,
nie porownuj tego do pilki noznej, tutaj liczby sa stale, w zuzlu nie ma zmiennej ilosci zawodnikow. Bazy danych projektuje sie pod konkretne rozwiazania, a nie zgodnie z jakas tam teoria. Jak juz mowimy o normalizacji, to zadam Wam pytanie: nigdy nie robicie redundancji w celu przyspieszenia czeogs? A wlasnie... jednak zdarzaja sie odstepstwa od teorii.
Crozin
Cytat
Chyba nie powiecie mi, ze lepiej miec 4x wiecej rekordow do przeszukiwania.
Tutaj? Zdecydowanie lepiej. Dodawanie, pobieranie (wyszukiwanie) i aktualizacja danych będzie w zdecydowanej większości przypadków szybsza. Ach, i najważniejsze. Praca programisty będzie wielokrotnie szybsza.

Cytat
Wam pytanie: nigdy nie robicie redundancji w celu przyspieszenia czeogs? A wlasnie... jednak zdarzaja sie odstepstwa od teorii.
Oczywiście, że się takie coś robi. Ale w większości przypadków nadal pozostawia się znormalizowane dane i jedynie część z nich dubluje na potrzeby jednego, dwóch czy pięciu mechanizmów. Dla reszty - i na przyszłość - pozostaje normalna forma danych.
phpion
@lukaskolista:
Tyle tylko, że już teraz ~emil1702 ma problem z sortowaniem danych. Później może chcieć uzyskać jakieś dodatkowe statystyki zawodników i znowu pojawią się problemy. Jeśli nie ma jasnych przesłanek ku temu by denormalizować strukturę bazy (np. wybitne kwestie wydajności) to moim zdaniem nie należy tego robić. Prędzej czy później dostaniemy pstryczka w nos wink.gif
lukaskolista
Cytat
Tyle tylko, że już teraz ~emil1702 ma problem z sortowaniem danych
Jezeli wszystko na sile chce zrobic po stronie bazy danych to ze wszystkim bedzie mial problemy.

  1. $result = mysql_quert("SELECT * FROM...");
  2. $row = mysql_fetch_object($result);
  3.  
  4. $times = array(
  5. $row->z1 => $row->cz1,
  6. $row->z2 => $row->cz2,
  7. $row->z3 => $row->cz3,
  8. $row->z4 => $row->cz4,
  9. );
  10.  
  11. asort($times);
  12.  
  13. echo '<pre>';
  14. var_dump($times);
juz nie ma problemu smile.gif

Edit:
Cytat
dodatkowo, aby czasy zawodnika 1 były zawsze oznaczone kolorem czerwonym, zaw 2 niebieskim itd.
tego to juz sie niestety w sortowaniu nie zrobi, podczas iteracji tablicy w 1 przebiegu trzeba pokolorowac element w HTML-u.
phpion
Hehe, no pewnie. Czasy (jak i inne dane) można zapisywać w postaci stringa bo przecież i tak będą sortowane w PHP wink.gif Nie popadajmy w skrajność. To może inny przykład: mamy w bazie X (dużo) informacji o biegach. Chcemy teraz pobrać informację o najszybszym zawodniku. Ok, można użyć LEAST, ale wówczas nie mamy możliwości skorzystania z ewentualnego indeksu.
lukaskolista
Cytat
Hehe, no pewnie. Czasy (jak i inne dane) można zapisywać w postaci stringa bo przecież i tak będą sortowane w PHP
Jak w postaci stringa? W bazie danych typ powinien byc float, a nie string, jeszcze ktos wezmie to do siebie i zacznie uzywac typu text do kolumn przechowujacych liczby zmiennoprzecinkowe.

Cytat
Ok, można użyć LEAST, ale wówczas nie mamy możliwości skorzystania z ewentualnego indeksu.
Tak, nie mamy takiej mozliwosci. W tym przypadku niestety trzeba skorzystac z 4 indexow, co jest faktycznie bez sensu. Ja tylko mowie, ze do tego konkretnego zastosowania ta struktura jest dobra smile.gif

Pozostaje pytanie: jak bardzo przerobka struktury bazy wplynie na aplikacje? Bo jesli trzebaby przerabiac pol aplikacje to nie wiem, czy jest sens.
Crozin
@lukaskolista: Na siłę bronisz swojego zdania, tak więc by uświadomić Ci jaką głupotę palnąłeś:
1. Pokaż zapytanie, które poza biegami i identyfikatorami zawodników (bo przecież tylko to tutaj mamy) pobierze: dane zawodnika takie jak imię nazwisko czy data urodzenia z tabeli z zawodnikami, listę osiągnięć dla każdego zawodnika (jeden zawodnik ma wiele osiągnięć) oraz listę ulubionych współzawodników zawodnika (relacja wiele-do-wielu pomiędzy zawodnikami).
2. Pokaż zapytanie, które poda średni czas przejazdu dla danego toru.
3. Pokaż zapytanie, które zwróci rekrod toru - najkrótszy czas przejazdu.

Prawo copy'ego-pasta może się tutaj przydać.
d3ut3r
Moim zdaniem lepiej przerobić ją dziś na spokojnie (a w międzyczasie zastosować półśrodek) niż jak baza będzie pokaźna i przeróbka będzie wymagana natychmiast.
phpion
Z tym typem pola to był żarcik. Skoro sortujesz w PHP to typ danych po stronie MySQL nie ma większego znaczenia.

Jeśli natomiast chodzi o sortowanie to nawet jeśli założysz 4 indeksy to nic Ci to nie da. Musiałbyś mieć indeks założony na LEAST(cz1, cz2, cz3, cz4) na co MySQL chyba nie pozwala (PostgreSQL już tak). Co do zmian w strukturze bazy: jeśli jest to początek to prac to moim zdaniem warto to za wczasu przerobić. Jeśli natomiast jest to już działający system to szkoda zachodu. Trzeba radzić sobie na tym, co jest.

@Crozin:
Co do Twoich "zadań".
1. Dołączenie danych zawodnika możesz zrobić aliasami - JOIN zawodnicy AS zawodnik_1. Pozostałe 2 punkty nie dotyczą tego konkretnego przypadku, a mając ID zawodnika można je pobrać mniej-więcej w analogiczny sposób.
2. AVG((cz1 + cz2 + cz3 + cz4) / 4).
3. MIN(LEAST(cz1, cz2, cz3, cz4)).

Nie twierdzę, że obecna struktura jest prawidłowa, bo nie jest. Prawda jest jednak taka, że postawione przez Ciebie zadania można spokojnie zrobić. Mniej wydajnie niż przy poprawnej strukturze, ale można wink.gif
lukaskolista
Crozin:
nie pokaze bo byloby troche pisania przy tym. Jak juz napisalem na samym poczatku: dobra do tego, konkretnego rozwiazania (jesli chodzi o sortowanie po czasie zawodnika). Do innych rozwiazan jest beznadziejna.

phpion:
Cytat
Musiałbyś mieć indeks założony na LEAST(cz1, cz2, cz3, cz4) na co MySQL chyba nie pozwala (PostgreSQL już tak)
Chodzi o index nalozony na wiecej, niz 1 kolumne?
phpion
Cytat(lukaskolista @ 25.06.2012, 11:48:36 ) *
Chodzi o index nalozony na wiecej, niz 1 kolumne?

Nie, o indeks będący wynikiem funkcji.
emil1702


Witajcie ponownie

Zmieniłem wygląd bazy na następujący:

id - idbieg - idzaw - czass - czas1 - czas2 - czas3 - czas4

czass - czas startu, czas1 - czas pierwszego okr itd

Jak teraz najlepiej posortować i pokolorować dane czasy, aby jak najmniej obciążać stronę.

Chciałbym, aby wyglądało to tak.

idzaw z najlepszym czas4, drugi, trzeci, czwarty.

najlepszy czass, drugi, trzeci, czwarty
najlepszy czas1, drugi, trzeci, czwarty itd

Kolory czasów według tabeli id, najniższa liczba to kolor czerwony, potem niebieski, biały i żółty
Crozin
Czy mnie oczy nie mylą czy masz dokładnie ten sam problem co w pierwszym poście?
emil1702
Cytat(Crozin @ 4.07.2012, 22:48:12 ) *
Czy mnie oczy nie mylą czy masz dokładnie ten sam problem co w pierwszym poście?

Zmieniłem układ tabeli według Waszych, m.in. Twojej podpowiedzi, ale chciałbym poznać Waszą opinię dotyczącą sposobu na najlepsze posortowanie tych danych.
d3ut3r
Cytat
Zmieniłem wygląd bazy na następujący:

id - idbieg - idzaw - czass - czas1 - czas2 - czas3 - czas4


Raczej nie o to nam chodziło smile.gif (Mi na pewno nie o to, Crozin podejrzewam również miał coś innego na myśli).

Chodziło mi o tabele:

Kod
Zawodnicy:

id|imie|nazwisko

Biegi:

id|nazwa_biegu

Wyniki

id_zawodnika|id_biegu|czas


i teraz, za pomocą selecta możesz pobrać wszystkich zawodników biorących udział w biegu x i posortować wg kolumny czas z tabeli wyniki.
emil1702
Cytat(d3ut3r @ 5.07.2012, 01:27:11 ) *
Raczej nie o to nam chodziło smile.gif

Zrobiłem oczywiście inne też, tylko ich nie podałem, bo chodzi mi teraz o operacje na jeden tabeli gdzie są czasy zawodników, czyli biegzaw. smile.gif
Kod
zawodnicy:
id | imie | nazwisko | wiek | umiejetnosc1 | umiejetnosc2 | talent | itd

mecz:

id | data | godzina | gosp | gosc | wynikgo | wynikgc

meczzaw:

id | idmecz | idteam | idzaw | pkt

bieg:

id | idmecz | nrbiegu | wynikgo | wynikgc

biegzaw:

id | idbieg | idzaw | czass | czas1 | czas2 | czas3 | czas4
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.