Code Lab is in development. New lessons and improvements are on the way. Progress can be deleted.
Loading…
Code Lab is in development. New lessons and improvements are on the way. Progress can be deleted.
Loading…
Code Lab is in development. New lessons and improvements are on the way. Progress can be deleted.
SQL / POSTGRESQL / Learn / LESSON 08
Ordinary aggregates SUM, AVG, COUNT, MIN and MAX become window functions once you add OVER. Without PARTITION BY they run over the whole result; with PARTITION BY, over the row's own part. That puts the detail next to the summary: a product's price and the average of its category, or an order and its customer's total.
A useful combination is the difference from the average: price - AVG(price) OVER (PARTITION BY category). Round money with ROUND(x, 2). AVG over NUMERIC is NUMERIC; COUNT returns an integer.
Aggregates inside OVER skip NULL (as usual). Rows with a NULL category form their own window — filter them if you do not want them.
Common mistakes: an aggregate without OVER in a query with non-grouped columns (GROUP BY error); missing rounding; PARTITION BY on the wrong column; expecting a row order.
Small example:
SELECT id, total, SUM(total) OVER (PARTITION BY customer_id) AS customer_spent FROM orders WHERE customer_id IS NOT NULL;
Working tables for this task. Grading also uses other datasets with the same schema.
| id | name | category | price |
|---|---|---|---|
| 1 | Atlas | books | 30 |
| 2 | Novel | books | 15 |
| 3 | Comic | books | 14.99 |
| 4 | Lamp | home | 29.99 |
| 5 | Vase | home | 30 |
| 6 | Rug | home | 45 |
| 7 | Hammer | tools | 15 |
| 8 | Drill | tools | 60 |
| 9 | Tape | tools | 15 |
| 10 | Candle | NULL | 8.5 |
| 11 | Gift Card | NULL | 25 |
| id | name | city |
|---|---|---|
| 1 | Mira | Sofia |
| 2 | Niko | Varna |
| 3 | Iva | Sofia |
| 4 | Alex | NULL |
| 5 | Boris | Plovdiv |
| 6 | Lena | Varna |
| 7 | Petya | Sofia |
| id | customer_id | total | order_date |
|---|---|---|---|
| 1 | 1 | 120 | 2024-01-05 |
| 2 | 1 | 35.5 | 2024-01-20 |
| 3 | 2 | 40 | 2024-01-20 |
| 4 | 3 | 99.99 | 2024-01-31 |
| 5 | NULL | 60 | 2024-02-01 |
| 6 | 1 | 40 | 2024-02-01 |
| 7 | 2 | 75.25 | 2024-02-14 |
| 8 | 3 | 100 | 2024-02-15 |
| 9 | 5 | 22 | 2024-02-15 |
| 10 | 1 | 39.99 | 2024-02-29 |
| 11 | 2 | 55 | 2024-03-01 |
| 12 | 3 | 18 | 2024-03-10 |
| 13 | 1 | 130 | 2024-03-15 |
| 14 | 2 | 40 | 2024-03-15 |
| 15 | 2 | 12.5 | 2024-03-31 |
| 16 | 3 | 47 | 2024-04-01 |
Expected columns: id, name, category, price, category_avg, diff · row order is not required
Expected result (displayed data):
Loading…Ordinary aggregates SUM, AVG, COUNT, MIN and MAX become window functions once you add OVER. Without PARTITION BY they run over the whole result; with PARTITION BY, over the row's own part. That puts the detail next to the summary: a product's price and the average of its category, or an order and its customer's total. A useful combination is the difference from the average: price - AVG(price) OVER (PARTITION BY category). Round money with ROUND(x, 2). AVG over NUMERIC is NUMERIC; COUNT returns an integer. Aggregates inside OVER skip NULL (as usual). Rows with a NULL category form their own window — filter them if you do not want them. Common mistakes: an aggregate without OVER in a query with non-grouped columns (GROUP BY error); missing rounding; PARTITION BY on the wrong column; expecting a row order.
QUERY STANDBY
›