Thursday, October 2, 2008

Oracle, cz. 2

Dzisiaj napiszę o czymś, co mnie nieco zakręciło i jest związane z agregacją.
Już jakiś czas temu korzystałem z funkcji MAX oraz GREATEST. Ale aż do dzisiaj nie miałem z nimi problemu.
W najprostszym przypadku można korzystać z nich zamiennie. Ale czasem różnice są znaczące.
Wyobraź sobie tabelę zawierającą pojedynczą kolumnę Col1 z liczbami od 1 do 9. Zapytanie SELECT MAX(Col1),GREATEST(Col1) FROM ... powinno zwrócić te same dane (ale nie sprawdzałem tego).
Jeśli chcesz znaleźć największą wartość w kolumnie - użyj MAX.
Jeśli chcesz dorzucić kolumnę zawierającą największą z wartości - użyj GREATEST.
Przykład:
INSERT INTO T VALUES (1,2,3),(5,6,2),(8,2,2)
SELECT Day1,Day2,Day3,GREATEST(Day1,Day2,Day3) FROM T
Otrzymasz wiersze (1,2,3,3),(5,6,2,6),(8,2,2,8)
SELECT MAX(Day1),MAX(Day2),MAX(Day3) FROM T
Otrzymasz wiersz (8,6,3)

A z czym miałem dzisiaj problem?
SELECT Col1, GREATEST(MAX(Day1), MAX(Day2), MAX(Day3)) Maximum FROM T GROUP BY Col1
Tutaj słowo wyjaśnienia: GROUP BY jest zbliżone do PARTITION BY (to drugie daje większe możliwości). Pozwala ono wykonać operację "SELECT Col1,MAX(Col2) FROM T GROUP BY Col1" - jak zapewne widzisz - chcę otrzymać wartości wkolumnie Col1. Dzięki GROUP BY otrzymam między 0 a n wierszy (gdzie n to ilość wierszy w tabeli T). Jeśli wartości w kolumnie Col1 się powtarzają - zostanie z nich wybrana największa. Inaczej mówiąc: podziel tabelę na grupy i wykonaj operację MAX/SUM/etc. na każdej grupie osobno.
Teraz wyjaśnienie mojego problemu: chciałem otrzymać kolumnę zawierającą największe z maksimów. Niestety Oracle nie poradzi sobie z tak nielogicznym zapytaniem: nie wiadomo czy do grupowania się tyczy funkcja MAX, czy też GREATEST (chciałem najpierw MAX a później GREATEST).
Rozwiązanie , które znalazłem, jest proste:
SELECT Col1, GREATEST(Max1,Max2,Max3) FROM ( SELECT Col1, MAX(Day1) Max1,MAX(Day2) Max2, MAX(Day3) Max3) FROM T GROUP BY Col1)

No comments: