programmera.net -> mysql -> normal     för utskrift      info@programmera.net

Aggregering i MySQL

1. Exempeltabell
2. COUNT()
3. MAX() och MIN()
4. AVG()
5. SUM()
6. GROUP BY
7. HAVING
8. ORDER BY

Normalt returnerar en SELECT-sats alla rader som uppfyller sökkriterierna i WHERE-delen. Så är dock inte alltid fallet, genom att använda aggregering sammanfattas dessa rader till en enda rad som innehåller någon typ av sammanfattande information som t.ex. kolumnens maxvärde, medelvärde eller liknande. Nedan sammanfattas de olika aggregeringsfunktionerna:

Aggregeringsfunktion Beskrivning
COUNT(col)  Denna funktion returnerar antal värden i kolumnen col.
MAX(col)  Denna funktion returnerar kolumnen cols maxvärde.
MIN(col)  Denna funktion returnerar kolumnen cols minvärde.
AVG(col)  Denna funktion returnerar medelvärdet av kolumnen cols.
SUM(col)  Denna funktion returnerar summan av kolumnen cols alla värden.

Aggregering kan kombineras med gruppering (GROUP BY) som medför att man kan göra flera aggregeringar i samma SELECT-sats.

1. Exempeltabell

Nedan skapas tabellen employee som vi kommer att använda nedan:
mysql> CREATE TABLE employee(	
	id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
	department VARCHAR(100) NOT NULL,
	name VARCHAR(100) NOT NULL,
	title VARCHAR(100),
	salary INT
	);

mysql> INSERT INTO employee (department, name, title, salary) VALUES
("Management", "Magnus", "President", 100000),
("Management", "Lisa", "Secretary", 30000),
("Sales","Jan","Sales Manager", 82000),
("Sales","Thomas","Sales", 73000),
("Sales","Marcus","Accountant", 58000),
("Development", "Jurgen", "CTO", 65000),
("Development", "Tobbe", "Programmer", 54000),
("Development", "Olle", "Programmer", 46000),
("Development", "Sven", "Programmer", 43000),
("Development", "Jocke", "Programmer", 47000);
	
mysql> SELECT * FROM employee;
+----+-------------+--------+---------------+--------+
| id | department  | name   | title         | salary |
+----+-------------+--------+---------------+--------+
|  1 | Management  | Magnus | President     | 100000 |
|  2 | Management  | Lisa   | Secretary     |  30000 |
|  3 | Sales       | Jan    | Sales Manager |  82000 |
|  4 | Sales       | Thomas | Sales         |  73000 |
|  5 | Sales       | Marcus | Accountant    |  58000 |
|  6 | Development | Jurgen | CTO           |  65000 |
|  7 | Development | Tobbe  | Programmer    |  54000 |
|  8 | Development | Olle   | Programmer    |  46000 |
|  9 | Development | Sven   | Programmer    |  43000 |
| 10 | Development | Jocke  | Programmer    |  47000 |
+----+-------------+--------+---------------+--------+
10 rows in set (0.00 sec)

2. COUNT()

Med COUNT kan man räkna antalet rader i returtabellen.
mysql> SELECT COUNT(*) FROM employee WHERE department="Sales";
+----------+
| COUNT(*) |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)
Man kan t. ex. räkna antalet unika värden i en kolumn:
mysql> SELECT COUNT(DISTINCT(department)) FROM employee;
+-----------------------------+
| COUNT(DISTINCT(department)) |
+-----------------------------+
|                           3 |
+-----------------------------+
1 row in set (0.00 sec)

3. MAX() och MIN()

Med funktionerna MAX och MIN kan man hitta det största och minsta värdet i en kolumn.
mysql> SELECT MAX(salary), MIN(salary) FROM employee;
+-------------+-------------+
| MAX(salary) | MIN(salary) |
+-------------+-------------+
|      100000 |       30000 |
+-------------+-------------+
1 row in set (0.00 sec)

4. AVG()

Med AVG så får man medelvärdet (average) på kolumnen:
mysql> SELECT AVG(salary) FROM employee;
+-------------+
| AVG(salary) |
+-------------+
|  59800.0000 |
+-------------+
1 row in set (0.00 sec)

5. SUM()

Med SUM beräknas summan av alla värden i kolumnen:
mysql> SELECT SUM(salary) FROM employee;
+-------------+
| SUM(salary) |
+-------------+
|      598000 |
+-------------+
1 row in set (0.00 sec)

6. GROUP BY

Funktionen GROUP BY möjliggör att man använder aggregeringsfunktioner som COUNT, MAX och MIN på flera delar av en tabell samtidigt. Jag tycker att GROUP BY är den svåraste funktionen i SQL, så den kan ta en stund att begripa sig på. Ett exempel på en SQL-fråga som kan besvaras med GROUP BY är "Visa medellönen för varje avdelning.":
mysql> SELECT department, COUNT(*), AVG(salary) FROM employee  
    -> GROUP BY department;
+-------------+----------+-------------+
| department  | COUNT(*) | AVG(salary) |
+-------------+----------+-------------+
| Development |        5 |  51000.0000 |
| Management  |        2 |  65000.0000 |
| Sales       |        3 |  71000.0000 |
+-------------+----------+-------------+
3 rows in set (0.00 sec)

7. HAVING

När du använder GROUP BY kan du ibland även behöva HAVING (som hamnar efter GROUP BY i SELECT-satsen). HAVING fungerar nästan som WHERE men med skillnaden:

  • WHERE opererar på enskilda rader i tabellerna. Om en urvalsmetod är "x > 5" kommer varje rad i den aktuella tabellen att valideras mot denna sats. Man kan alltså inte använda aggregeringsfunktioner i WHERE eftersom WHERE utför sina urval på enskilda rader.
  • HAVING opererar på de rader som bildas efter att GROUP BY har utförts, vilket betyder att man kan använda aggregeringsfunktioner i urvalet.
I exemplet nedan har vi bestämt oss för att vi bara vill se medellönen för avdelningar med fler än 3 anställda:
mysql> SELECT department, COUNT(*), AVG(salary) FROM employee  
    -> GROUP BY department HAVING COUNT(*) > 3;
+-------------+----------+-------------+
| department  | COUNT(*) | AVG(salary) |
+-------------+----------+-------------+
| Development |        5 |  51000.0000 |
+-------------+----------+-------------+
1 row in set (0.00 sec)
Endast en avdelning uppfyller kriteriet att ha fler än 3 anställda.

8. ORDER BY

ORDER BY kan sortera efter grupper, men kravet är att kolumen har ett alias. I exemplet nedan vill vi att den avdelning som har den högsta medellönen ska hamna högst i listan, därför skapar vi ett alias "Avg_Sal" som vi sedan använder för sorteringen:
mysql> SELECT department, COUNT(*), AVG(salary) AS Avg_Sal FROM employee 
    -> GROUP BY department ORDER BY Avg_Sal DESC;
+-------------+----------+------------+
| department  | COUNT(*) | Avg_Sal    |
+-------------+----------+------------+
| Sales       |        3 | 71000.0000 |
| Management  |        2 | 65000.0000 |
| Development |        5 | 51000.0000 |
+-------------+----------+------------+
3 rows in set (0.00 sec)
Försöker vi att sortera på "AVG(salary)" så protesterar MySQL:
mysql> SELECT department, COUNT(*), AVG(salary) FROM employee 
   -> GROUP BY department ORDER BY AVG(salary) DESC;
ERROR 1111: Invalid use of group function