Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL]Średnia z kilku wierszy
Forum PHP.pl > Forum > Przedszkole
ShadowD
Hej, mam 2 tabele, w jednej userów/ogłoszenia, a w drugiej wyniki głosowania na nich w formie jeden wiersz jedna ocena, więc każdy user ma dużo wierszy należących do niego.

Chciał bym pobrać trzy osoby z największą średnią punktów, wiem że bez sensu jest pobierać wszystko i za pomocą php to obliczać, bo za każdym razem powtarzanie takiej operacji zamuli całość, mam cos takiego:
  1. SELECT * FROM wp_ankiety ankiety
  2. JOIN wp_posts post ON (ankiety.id_post=post.id AND )

Pobieram tym wszystkie oferty i odpowiadające im wpisy, teraz chciał bym napisać warunek zliczający oceny i wyciągający ich średnią, następnie pobrał trzy. Mam taką bazę do ankiet:

id id_post type ip ocena

Nie muszę dostać rozwiązania na tacy, a sposób jak zliczać i dzielić w zapytaniach - nie mam pojęcia jak coś takiego wykonać.
mat-bi
AVG
kacper.chrapa
Witam :-)

Pozwole sobie inaczej nazwac tabelki na potrzeby dydaktyczne - meczacy dzien i nie chce mi sie deszyfrowac co jest co u Ciebie ;-) A w koncu nie chciales rozwiazania na tacy ;-))

Jesli tabelki to:

1. uzytkownicy

id_uzytkownika
imie
nazwisko
...

2.oceny

id_oceny
id_uzytkownika
ocena INT/DECIMAL
...


To problem rozwiazesz np. tak :

1. Łączymy tabelki po id uzytkownika:
  1. SELECT * FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3.  



W ten sposob, do kazdego wiersza z ocena podepnie sie odpowiedni user. Bedzie ladna, duza tabelka ;-)

2. Teraz, pobierz tylko te dwie kolumny (dlaczego tylko te - bedzie pozniej)
  1. SELECT o.id_uzytkownika,o.ocena FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)



3. Nastepnie, jak zasugerowal kolega - ocene traktujemy funkcja agregujaca AVG - ona obliczy srednia.
  1. SELECT o.id_uzytkownika,AVG(o.ocena) AS srednia FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3.  

Chwilowo, dostaniesz tylko jeden wiersz. Cos w rodzaju:

id_uzytkownika | srednia
123 4.34

AVG obliczylo srednia artymetyczna wszystkich ocen, a id_uzytkownika jest przypadkowe. UWAGA: jesli masz bardziej restrykcyjne ustawienia serwera MySQL lub pracujesz w PostgreSQL,
dostaniesz błąd. Zignoruj go chwilowo (pozniej wyjasnienie) - i przejdz do punktu 4 .

4. Zeby AVG zadzialalo na kazdym userze osobno , musisz wlaczyc grupowanie na kolumnie id_uzytkownika.


  1. SELECT o.id_uzytkownika,AVG(o.ocena) AS srednia FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3. GROUP BY o.id_uzytkownika

Dostaniesz cos w rodzaju:

id_uzytkownika | srednia
122 | 3.43
123 | 4.54
434 | 3.44
... .....

Czyli mamy numerki userow oraz ich srednie :-)

5. Teraz sortujemy malejaco wg sredniej:

  1. SELECT o.id_uzytkownika,AVG(o.ocena) AS srednia FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3. GROUP BY o.id_uzytkownika
  4. ORDER BY srednia DESC


6. Wyciagamy pierwsze 3 rekordy:


  1. SELECT o.id_uzytkownika,AVG(o.ocena) AS srednia FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3. GROUP BY o.id_uzytkownika
  4. ORDER BY srednia DESC
  5. LIMIT 3



7. I na koniec - wyciagamy imie i nazwisko :
  1. SELECT o.id_uzytkownika,AVG(o.ocena) AS srednia,u.imie,u.nazwisko FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3. GROUP BY o.id_uzytkownika
  4. ORDER BY srednia DESC
  5. LIMIT 3



Wazne: jesli twoj mysql bardziej sie trzyma standardow (lub dzialasz np. w postgresie), teraz bedziesz mial blad jak w punkcie 3.
Aby go rozwiazac, podaj na liscie grupowania kolumny imie i nazwisko:

  1. SELECT o.id_uzytkownika,AVG(o.ocena) AS srednia,u.imie,u.nazwisko FROM oceny o JOIN uzytkownicy u
  2. ON (u.id_uzytkownika=o.id_uzytkownika)
  3. GROUP BY o.id_uzytkownika, u.imie, u.nazwisko
  4. ORDER BY srednia DESC
  5. LIMIT 3


Czemu tak jest - troche zakrecone do wyjasnienia , a jest sobota ;-) Ale wystarczy ze zapamietasz, ze zgodnie ze standardem jak uzywasz f. agregujacych, to wyswietlane kolumny nie podlegajace agregacji
musisz potraktowac group by (heh heh - mysql zwykle tego nie wymusza, i latwo mozna nie zauwazyc bzdurnych wynikow w okreslonych sytuacjach).


Dodatkowo, jesli bedziesz czesto wyswietlal wyniki, zaloz index na kolumne id_uzytkownika w tabeli oceny (tj., na ich odpowiednik u Ciebie;-).



Pozdrowka serdeczne,
Kacper

p.s. a jesli masz chec sie doszkolic - zapraszam na szkolenie z MySQL+PostgreSQL (zaawansowany SQL, programowanie plpgsql, triggery, ograniczenia, wydajnosc). Zaprojektowane pod kątem programistow:-)
http://www.edusequence.com/szkolenie_mysql...ql/wprowadzenie




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.