1SELECT drink,2 COUNT(*), SUM(price)3FROM orders4GROUP BY drink5HAVING SUM(price) > 56ORDER BY drink;drink count sumlatte 3 13mocha 2 9latte#1 4#3 4#6 5COUNT 3SUM 13id drink price1 latte 42 tea 23 latte 44 mocha 55 tea 36 latte 57 mocha 4tea#2 2#5 3COUNT 2SUM 5mocha#4 5#7 4COUNT 2SUM 94245354Σ 27price
Back: the SQL query (one clause per line) and the resultFront: the orders table and one tray per drink (a group)Pucks: prices moving into totals and groups; envelopes: the answer rowsAt the back: the SQL query and the result it gets back. In front: the café's orders table and one tray per drink. GROUP BY drink sorts the 7 rows into 3 trays; COUNT(*) and SUM(price) collapse each tray into one row; HAVING SUM(price) > 5 drops tea; SELECT and ORDER BY give latte 3 13 and mocha 2 9. Without ORDER BY, SQL does not promise any order for the groups in an answer. The figure lines up the groups in the order their first row appears.

Aggregates

  1. An aggregate function turns many values into one. COUNT(*) counts rows; SUM(price) adds up a column. Over all 7 café orders, COUNT(*) is 7 and SUM(price) is 27.

GROUP BY, step by step

The rules

What happens

;; step 1/9 · aggregate
aggregate function   many values in, one value out
  COUNT(*)     how many rows
  SUM(price)   add up the prices
  AVG, MIN and MAX work the same way

  id  drink  price
  1   latte  4
  2   tea    2
  3   latte  4
  4   mocha  5
  5   tea    3
  6   latte  5
  7   mocha  4

SELECT COUNT(*), SUM(price) FROM orders;
  count 7   sum 27
  4 + 2 + 4 + 5 + 3 + 5 + 4 = 27

Without ORDER BY, SQL does not promise any order for the groups in an answer. The figure lines up the groups in the order their first row appears. COUNT(*) counts rows. COUNT(price) and SUM(price) skip empty (NULL) prices. Over no rows at all, COUNT gives 0 but SUM, AVG, MIN and MAX give NULL.