Modulelessen (3/4)
Groeperen met GROUP BY
In Module 2 heb je geleerd dat COUNT(*), AVG(...), SUM(...) alle
rijen naar een enkele resultaatrij. Maar wat als je een gemiddeld salaris wilt?
voor elke afdeling, niet voor het hele bedrijf? U wilt één rij per
groep. Dat is de taak van GROUP BY.
De syntaxis
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column;Lees in het Engels: "splits de rijen in groepen die dezelfde waarde delen van
grouping_column, en bereken voor elke groep het totaal ".
-- Average salary per department:
SELECT department_id, AVG(salary) AS average
FROM employees
GROUP BY department_id;Het resultaat bevat één rij voor elke afzonderlijke department_id gevonden in
BESCHERMD_INLINE_6. Je krijgt 5 rijen: één voor elk van de 4 afdelingen (1, 2,
3, 4) plus één voor NULL (Andrea Costa).
Met JOIN voor leesbare namen
Vaak wilt u groeperen op department_id, maar toont u de naam van de
afdeling. Je combineert GROUP BY met een JOIN:
SELECT d.name AS department,
COUNT(*) AS count,
AVG(e.salary) AS average_salary
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
GROUP BY d.name
ORDER BY count DESC;Dit is een volwaardige business intelligence-query: in drie regels vertelt u hoeveel medewerkers elke afdeling heeft en hoeveel ze verdienen gemiddeld, gesorteerd van groot naar klein.
De gouden regel
Wanneer u GROUP BY gebruikt, moet elke kolom in SELECT zijn:
- een van de groeperingskolommen (bijvoorbeeld
department_id,d.name), of - binnen een aggregatiefunctie (bijvoorbeeld
AVG(salary),COUNT(*)).
-- ERROR: first_name is neither in GROUP BY nor inside an aggregate
SELECT department_id, first_name, AVG(salary)
FROM employees
GROUP BY department_id;PostgreSQL retourneert een expliciete fout ("kolom moet verschijnen in het bestand GROUP BY
clausule of worden gebruikt in een aggregatiefunctie"). Het is een gebruikelijke vroege week
fout: als je het ziet, stop dan en vraag jezelf af: wat is de waarde ervan
first_name voor een groep van 3 personen?"_ — er is geen eenduidig antwoord, en
daarom weigert de motor.
Probeer het
Bereken voor elke afdeling hoeveel medewerkers deze bevat. Retourneer twee kolommen: de afdelingsnaam (departments.name) en het aantal werknemers. Eén rij per afdeling.
Toon hint
Aggregeren met COUNT(*) en groeperen op d.name. De SELECT mag alleen de groeperingskolom en de aggregatie bevatten.
Oplossing beschikbaar na 3 pogingen
Oefening beoordelen
Bereken voor elke afdeling (departments.name) het gemiddelde salaris (AVG(salaris)) van de medewerkers, gesorteerd van hoog naar laag.
Toon hint
AVG(e.salaris) als totaal, GROEP OP d.naam, ORDER OP gemiddelde DESC.
Oplossing beschikbaar na 3 pogingen