Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: zapytanie grupujace + pola z poza GROUP BY
Forum PHP.pl > Forum > Bazy danych > MySQL
BartT
Proszę o pomoc w skonstruowaniu (i zrozumieniu jak to się robi) zapytania sql które uzupełni kwerendę agregującą o inne dane na temat rekordów będących wynikiem tej agregacji.
Mam 2 tabele: dystanse (półmaraton, 10km, itd.) oraz wyniki zawodnika na poszczególnych dystansach.
Chcę znaleźć najlepsze wyniki dla każdego z dystansów.
Kwerenda grupująca po dystansach z funkcją agregująca min(czas) musi być oparta na danych z więcej niż 1 tabeli powiązanych relacją LEFT JOIN.
Taka kwerenda daje te najkrótsze czasy (z funkcji min(*) w klauzuli SELECT) oraz pola z klauzuli GROUP BY (w tym wypadku dystans).
Nie potrafię natomiast uzupełnić tego zestawienia o identyfikatory rekordów dla których znaleziono te najkrótsze czasy oraz inne pola z tabeli dowiązanej przez JOIN (tabela dystansów).
Chodzi o to, że jeśli do klauzuli SELECT dodam coś co nie jest ani argumentem funkcji agregującej ani parametrem grupowania z klauzuli GROUP BY to w wynikach pojawia się w tym polu przypadkowa (a w każdym razie błędna) wielkość.

Mam taki kod:
  1. SELECT
  2. `results`.user, `races`.raceTypeId, `raceSelection`.nominalDistance,
  3. min(`results`.time) AS personalBest,
  4. count(*) AS numberOfResults
  5.  
  6. /*
  7. Potrzebne są także dodatkowe poniższe pola:
  8.  
  9. `results`.resultId, (identyfikator rekordu z najkrótszym czasem)
  10. `competitions`.name, (nazwa i data zawodów kiedy w których osiągnięto ten najlepszy wynik)
  11. `competitions`.date
  12.  
  13. ale w ten sposób to nie ma prawa działać :-(
  14. */
  15.  
  16. FROM
  17.  
  18. `results`
  19. LEFT JOIN `races` USING (raceId)
  20. LEFT JOIN `raceSelection` USING (raceSelectionId)
  21. LEFT JOIN `competitions` USING (competitionId)
  22.  
  23. GROUP BY `results`.user, `races`.raceTypeId, `raceSelection`.nominalDistance
  24.  
  25.  


Pozdrawiam
Bart
mmmmmmm
Zasada jest prosta:
do grupowania dajesz WSZYSTKIE kolumny z zapytania, przy których nie ma funkcji agregującej.

Jak to zapamiętasz, to NA KAŻDYM SZBD zapytanie pójdzie.
Ale są wyjątki ułatwiające, które oczywiście już nie wszędzie działają:
1. Możesz grupować wg numerów kolumn np. SELECT imie, count(id), nazwisko FROM tabela GROUP BY 1,3 da taki sam wynik jak SELECT imie, count(id), nazwisko FROM tabela GROUP BY imie, nazwisko
2. przy kliku polach z danej tabeli, jeśli w zapytaniu wypisujesz również klucz główny (np. ID), to wystarczy że wg niego pogrupujesz np. SELECT id, imie, nazwisko, COUNT(*) FROM tabela GROUP BY id
3. Nie musisz wypisywać stałych do grupowania np. SELECT imie, nazwisko, 'AKTYWNY' status, Count(*) FROM tabela GROUP BY 1,2 to to samo co SELECT imie, nazwisko, 'AKTYWNY' status, Count(*) FROM tabela GROUP BY 1,2,3

Jeszcze parę uwag:
Do twojego zapytania niepotrzebne są LEFT JOINy -tak mi się wydaje. Bez nich zapytanie dostanie kopa (o ile masz dobre indeksy)
Nie używaj Count(*) zwłaszcza przy LEFT JOINach - może dać ci wyniki, nie takie jakie byś chciał. Lepiej użyj Count(tabela.id)
BartT
mmmmmmm nie rozumiem...
>> do grupowania dajesz WSZYSTKIE kolumny z zapytania, przy których nie ma funkcji agregującej.
W sensie do klauzuli GROUP BY?
Tak przecież mam.
Grupowanie zachodzi u mnie prawidłowo. Poszukuję sposobu na uzyskanie pól po których NIE chcę grupować ani NIE agreguję tych wartości:
- np. Id rekordu który okazał się mieć min(czas) w każdej grupie,
albo nazwę zawodów z tabeli `competition

Inaczej mówiąc na podstawie zapytania grupującego i agregującego dla grup chcę uzyskać coś co jest powiązane z wynikami takiego zapytania agregującego.
trueblue
Temat: grupowanie z jednym polem max
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-2024 Invision Power Services, Inc.