Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Dwie funkcje agregujące
paaax
post 26.01.2010, 20:13:58
Post #1





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 16.08.2008

Ostrzeżenie: (0%)
-----


Witam,

Posiadam prostą bazę danych szkoły, w której znajdują się tabele: students, teachers, courses i tsc (w której znajdują się informacje o tym jaki student miał jaki przedmiot, jak długo i z którym wykładowcą oraz ocena z tego przedmiotu). Na tej bazie próbuję np. zrealizować zapytanie wyboru roku studiów, na którym jest najwyższa średnia. Robię to w taki sposób:

  1. SELECT TOP 1 STUDYEAR, AVG(GRADE) AS ILE FROM COURSES, TSC
  2. WHERE COURSES.CNO = TSC.CNO
  3. GROUP BY STUDYEAR ORDER BY 2 DESC;


Co działa, ale nie w przypadku, gdy kilka lat ma tę samą średnią i trzeba wyświetlić wszystkie. Zapytanie poniższe nie działa (pracuje pod SQL Serverem):

  1. SELECT T.STUDYEAR, T.SREDNIA FROM (SELECT STUDYEAR, AVG(GRADE) SREDNIA FROM COURSES, TSC
  2. WHERE COURSES.CNO = TSC.CNO
  3. GROUP BY STUDYEAR) T
  4. WHERE T.SREDNIA = (SELECT MAX(SREDNIA) FROM T)


Istnieje jakiś prosty sposób realizowania tego typy zapytań, gdzie muszę użyć kilka razy funkcji agregujących razem z grupowaniem, bez korzystania z tabel tymczasowych? Ogólnie mam kilka tego typu zapytań (np. wybór najwyższej średniej, największej liczby przedmiotów ze wszystkich lat, przedmiotu, na który uczęszczało najmniej osób itp.). Chciałbym wiedzieć, jak najoptymalniej realizować tego typu zapytania.
Go to the top of the page
+Quote Post
Zyx
post 27.01.2010, 08:12:46
Post #2





Grupa: Zarejestrowani
Postów: 952
Pomógł: 154
Dołączył: 20.01.2007
Skąd: /dev/oracle

Ostrzeżenie: (0%)
-----


Niestety musisz powielić podrzędne zapytanie wyliczające średnią także w podzapytaniu obliczającym MAX i liczyć, że optymalizator sobie to wykryje:

  1. SELECT t.`studyear` FROM (SELECT `studyear`, AVG(`grade`) AS `ile` FROM `courses`, `tsc`
  2. WHERE `courses`.`id` = `tsc`.`id_course`
  3. GROUP BY `studyear` ORDER BY 2 DESC) t
  4. WHERE t.`ile` = (SELECT MAX(p.`ile`) FROM (SELECT `studyear`, AVG(`grade`) AS `ile` FROM `courses`, `tsc`
  5. WHERE `courses`.`id` = `tsc`.`id_course`
  6. GROUP BY `studyear` ORDER BY 2 DESC) p)


Chodzi o to, że o ile podzapytania mogą być skorelowane z nadrzędnymi, to już muszą mieć całkowicie własne definicje tabelek. Ponieważ średnią wyliczasz w locie, musisz powielić całe liczące ją zapytanie. Jeśli napisałbyś samo

  1. WHERE t.`ile` = (SELECT MAX(t.`ile`))


Wartość MAX byłaby policzona dla każdego wiersza osobno i ogólnie nie działałoby to tak, jak trzeba.

Aktualnie nie mam SQL Servera pod ręką, więc napisałem w innym dialekcie, ale myślę, że dasz radę sobie przerobić smile.gif.


--------------------
Specjalista ds. głupich i beznadziejnych, Zyx
Nowości wydawnicze: Open Power Collector 3.0.1.0 | Open Power Autoloader 3.0.3.0
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 1.05.2025 - 05:28