Sposób nr 1:
Potrzebujesz wyciągnąć informacje o pracownikach, którzy zarabiają najwięcej w obrębie poszczególnych działów. Problem w tym, że takiej danej, tzn. jakie są maksymalne zarobki w obrębie danego działu, nie masz. Gdybyś jednak miał, to zapytanie mogłoby wyglądać następująco:
SELECT t1.Dzial, t1.Imie, t1.Wynagrodzenie
FROM SomeTable AS t1
WHERE t1.Wynagrodzenie = t1.MaxWynagrodzenie
(t1 to jak słusznie zauważyłeś alias) Trzeba, więc coś podstawić w miejsce t1.MaxWynagrodzenie. Gdybyś chciał zdobyć informację o maksymalnym wynagrodzeniu w obrębie danego działu, to użyłbyś zapewne takiego zapytania:
SELECT MAX(t2.Wynagrodzenie)
FROM SomeTable AS t2
WHERE t2.Dzial = 1 -- Np. Dział nr 1
Pytanie jak powiązać to z powyższym zapytaniem? Żeby to zrobić, trzeba użyć czegoś, co nazywa się podzapytanie skorelowane (nie wiem kto to tak nazwał
). Nazwa wzięła się stąd, że podzapytanie to korzysta z parametrów przekazanych z (nazwijmy to) nadrzędnego zapytania. U nas tym parametrem przekazanym z nadrzędnego zapytania będzie numer działu (t1.Dzial). W efekcie całość wygląda następująco:
SELECT t1.Dzial, t1.Imie, t1.Wynagrodzenie
FROM SomeTable AS t1
WHERE t1.Wynagrodzenie = (
SELECT MAX(t2.Wynagrodzenie)
FROM SomeTable AS t2
WHERE t2.Dzial = t1.Dzial
)
Reasumując działa to tak, że dla każdego rekordu wyciąganego z tabeli SomeTable wykonywane jest podzapytanie, które sprawdza, jaka jest maksymalna wysokość wynagrodzenia w dziale, do którego odnosi się dany rekord. Sposób nr 2: Jeśli zrozumiałeś, to o czym pisałem wyżej (jeśli nie zrozumiałeś, to jest to moja wina), to zapewne zauważyłeś, że tamto zapytanie ma jedną wadę. Wielokrotnie jest sprawdzane, jaka jest maksymalna wysokość wynagrodzenia w danym dziale. Dokładniej mówiąc … tyle ile masz rekordów w tabeli SomeTable, tyle razy zostanie wykonane ww. podzapytanie skorelowane. Lepszym sposobem jest wyciągnięcie tych danych (maksymalnych wynagrodzeń) na samym początku, żeby nie powielać wielokrotnie tej samej czynności. Żeby osiągnąć taki efekt należy utworzyć sobie tabelę tymczasową. Kod jaki użyłem do utworzenia tej tabeli jest następujący:
SELECT t.Dzial AS Dzial, MAX(t.Wynagrodzenie) AS MaxWynagrodzenie
FROM SomeTable AS t
GROUP BY t.Dzial
Jak działa Group By znajdziesz w Internecie (ja tu się nie będę produkował
). Cel tego zapytania jest taki, że zwróci ono dane w postaci: Dzial | MaxWynagrodzenie Mając to można zapisać takie zapytanie:
SELECT *
FROM SomeTable AS t1, (
SELECT t.Dzial AS Dzial, MAX(t.Wynagrodzenie) AS MaxWynagrodzenie
FROM SomeTable AS t
GROUP BY t.Dzial
) AS t2
(aliasy nie muszą się nazywać t1 i t2, możesz wpisać co chcesz). Najlepiej wykonaj je i zobacz jakie dostaniesz wyniki. Dlaczego otrzymałeś takie, a nie inne? Jeśli w klauzuli FROM podasz kilka nazw tabel oddzielonych przecinkami, to między rekordami tych tabel, wykonany zostanie iloczyn kartezjański. Mówiąc po ludzku, wynikowa tabela będzie zawierała wszystkie możliwe kombinacje rekordów. Oczywiście nas takie rozwiązanie zupełnie nie zadowala. Dany rekord z tabeli oznaczonej aliasem t1 potrzebujemy powiązać tylko i wyłącznie z jednym konkretnym rekordem z tabeli tymczasowej oznaczonej aliasem t2 (a nie z każdym z nich). Żeby te rekordy powiązać używamy nazwy działu, która pojawia się zarówno w tabeli oznaczonej aliasem t1, jak i tabeli tymczasowej oznaczonej aliasem t2. Wykonaj następujące zapytanie i przeanalizuj wyniki:
SELECT *
FROM SomeTable AS t1, (
SELECT t.Dzial AS Dzial, MAX(t.Wynagrodzenie) AS MaxWynagrodzenie
FROM SomeTable AS t
GROUP BY t.Dzial
) AS t2
WHERE t1.Dzial = t2.Dzial
Wszystko już jest prawie gotowe. Pozostało dodać jeszcze tylko jeden warunek do klauzuli WHERE i ostatecznie otrzymujemy:
SELECT t1.Dzial, t1.Imie, t1.Wynagrodzenie
FROM SomeTable AS t1, (
SELECT t.Dzial AS Dzial, MAX(t.Wynagrodzenie) AS MaxWynagrodzenie
FROM SomeTable AS t
GROUP BY t.Dzial
) AS t2
WHERE t1.Dzial = t2.Dzial AND t1.Wynagrodzenie = t2.MaxWynagrodzenie