Dziś powtórzymy zasadę działania klauzuli GROUP BY.
Skorzystamy z bezpłatnej bazy Oracle HR dostępnej tutaj:
http://www.oracle.com/technetwork/database/express-edition/downloads/index.html
Jeżeli wpiszemy proste wyrażenie pokazane poniżej, otrzymamy informację o błędzie. Funkcja AVG oblicza średnie wynagrodzenie z tabeli EMPLOYEES.
SELECT
DEPARTMENT_ID,
AVG(SALARY)
FROM EMPLOYEES;
Niezbędne jest dopisanie klauzuli GRUPED BY, która dedykowana jest do wszystkich funkcji, które podają jeden wspólny wynik dla wskazanej kolumny.
Table of Contents
ToggleKlauzula GRUPED BY
Schemat działania klauzuli GRUPED BY jest następujący: najpierw po SELECT pojawia się jakaś funkcja wynikowa w połączeniu z nazwami grup. Taki zestaw danych nie może być wyświetlony ponieważ wynik jest jeden a grup jest kilka. Na końcu konieczna jest więc klauzula GRUPED BY.
Prawidłowa składnia powinna wyglądać tak:
Prawidłowe zapytanie ma formę:
SELECT
DEPARTMENT_ID,
AVG(SALARY)
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID;
Otrzymujemy tabelę wynikową:
Klauzula HAVING
Na końcu tego wpisu zagnieździmy podzapytanie zawierające klauzulę HAVING. Tym razem będzie prosty warunek z HAVING.
Klauzula HAVING w połączeniu z GROUP BY operuje na całych grupach nie na pojedynczych rekordach
SELECT
DEPARTMENT_ID,
AVG(SALARY)
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID
HAVING AVG(SALARY) < 6501
Klauzula HAVING uszczegóławia zapytanie. Najpierw funkcja AVG oblicza średnią. Dzięki klauzuli GROUP BY wyniki średnie zostają pogrupowane. Następnie klauzula HAVING wyświetla tylko to, co jest zgodne z zadanym warunkiem.
Klauzula HAVING nie może istnieć bez klauzuli GROUP BY
Funkcje agregujące (nazwane tutaj funkcjami jednego wyniku) umieszczane są po SELECT i po HAVING
W naszym przypadku jest to średnia pensja niższa od 6 500.
Teraz wyświetlimy wszystkie działy, w których jest zatrudnionych więcej niż 15 pracowników lub mniej niż 3.
SELECT
JOB_ID,
COUNT(LAST_NAME)
FROM EMPLOYEES
GROUP BY JOB_ID
HAVING COUNT(LAST_NAME) > 15 OR COUNT(LAST_NAME)<5;
Po klauzuli HAVING musi znajdować się to samo wyrażenie, co po instrukcji SELECT
Otrzymujemy tabelę wynikową:
Kolejny przykład: raport na temat prowizji.
SELECT
JOB_ID,
AVG(COMMISSION_PCT)
FROM EMPLOYEES
GROUP BY JOB_ID
HAVING AVG(COMMISSION_PCT) < 0.3
Klauzula HAVING ma znajdować się po GROUP BY i przed klauzulą OREDER BY
Chcemy dowiedzieć się, w którym dziale średnia pensja jest półtora raza większa od średniej pensji wszystkich działów. Tym razem jest to zagnieżdżenie zapytań z klauzula HAVING.
SELECT
DEPARTMENT_ID,
AVG(SALARY)
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID
HAVING AVG(SALARY)>
(SELECT
1.5*(AVG(SALARY))
FROM EMPLOYEES);
Otrzymujemy tabelę wynikową:
Schemat użycia klauzuli GROUP BY z HAVING
Klauzula HAVING w połączeniu z GROUP BY wskazuje nam grupy spełniające zadany warunek
Funkcje agregujące (nazwane tutaj funkcjami jednego wyniku) umieszczane są po SELECT i po HAVING.
Użycie HAVING I WHERE w jednym zapytaniu
Chcemy dowiedzieć się ile wynosiła suma wynagrodzeń dla poszczególnych typów stanowisk. Założyliśmy warunek, że nie bierzemy do sumy pojedynczych wynagrodzeń większych od 8 000 oraz, że nie interesują nas sumy wynagrodzeń dla poszczególnych stanowisk, które przekroczą 20 000.
SELECT
JOB_ID,
SUM(SALARY) AS Suma_wynagrodzeń
FROM EMPLOYEES
WHERE SALARY < 8000
GROUP BY JOB_ID
HAVING SUM(SALARY) < 20000;
Otrzymujemy tabelę wynikową:
Tym razem zrobimy raport wielkości wynagrodzeń i średnich wynagrodzeń dla poszczególnych działów.
SELECT
DEPARTMENTS.DEPARTMENT_NAME,
SUM(EMPLOYEES.SALARY) AS SUMA_WYNAGRODZEŃ,
ROUND(AVG(EMPLOYEES.SALARY)) AS ŚREDNIE_WYNAGRODZENIE
FROM EMPLOYEES, DEPARTMENTS
WHERE EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID
GROUP BY DEPARTMENTS.DEPARTMENT_NAME
ORDER BY SUMA_WYNAGRODZEŃ DESC;
Otrzymujemy tabelę wynikową:
Teraz zrobimy raport wynagrodzeń dla kategorii stanowisk. Raport będzie uwzględniał średnie wynagrodzenie, maksymalne i minimalne wynagrodzenie oraz ilość stanowisk pracy w danej kategorii stanowisk.
SELECT
EMPLOYEES.JOB_ID,
MIN(EMPLOYEES.SALARY),
MAX(EMPLOYEES.SALARY),
AVG(EMPLOYEES.SALARY),
COUNT(EMPLOYEES.SALARY) AS ILOŚĆ_PRACOWNIKÓW
FROM EMPLOYEES, JOBS
WHERE EMPLOYEES.JOB_ID = JOBS.JOB_ID
GROUP BY EMPLOYEES.JOB_ID;
Otrzymujemy tabelę wynikową:










