SQL Aggregate Calculations
Aggregate results are just numbers — ordinary arithmetic works directly on them, letting a query compute derived business metrics in one step.
What & Why
Once an aggregate function produces a value, it behaves exactly like any other number in the query — it can be added, multiplied, divided, or combined with other aggregates using ordinary arithmetic operators, right there in the same SELECT list. This is how a single query ends up computing a genuinely derived business metric, not just a raw sum or average.
See How It Works
Marketing wants the conversion rate for leads from each source.
| id | campaign_id | created_at | qualified_at | converted_at | lead_score | source | country | |
|---|---|---|---|---|---|---|---|---|
| 301 | 1 | ana@example.com | 2024-01-21 09:10:00+00 | 2024-01-22 11:00:00+00 | 2024-02-02 10:00:00+00 | 86 | google_ads | US |
| 302 | 1 | ben@example.com | 2024-01-24 12:40:00+00 | NULL | NULL | 52 | google_ads | CA |
| 303 | 2 | chloe@example.com | 2024-02-16 08:30:00+00 | 2024-02-18 14:20:00+00 | NULL | 74 | GB | |
| 304 | 3 | dev@example.com | 2024-03-20 17:15:00+00 | 2024-03-21 09:00:00+00 | 2024-04-04 16:00:00+00 | 91 | US |
SELECT
source,
COUNT(*) AS leads,
COUNT(*) FILTER (WHERE converted_at IS NOT NULL) AS conversions,
ROUND(100.0 * COUNT(*) FILTER (WHERE converted_at IS NOT NULL) / NULLIF(COUNT(*), 0), 2) AS conversion_rate
FROM marketing.leads
GROUP BY source
ORDER BY conversion_rate DESC NULLS LAST, source;| source | leads | conversions | conversion_rate |
|---|---|---|---|
| 1 | 1 | 100.00 | |
| google_ads | 2 | 1 | 50.00 |
| 1 | 0 | 0.00 |
The conversion numerator and denominator come from the same source group.
Practice this concept
Marketing wants the conversion rate for leads from each source.
marketingPrefix tables with marketing.table_name.
sourceleadsconversionsconversion_ratemarketing.leads| Column | Type |
|---|---|
| id | integer |
| campaign_id | integer |
| text | |
| created_at | timestamp with time zone |
| qualified_at | timestamp with time zone |
| converted_at | timestamp with time zone |
| lead_score | integer |
| source | text |
| country | text |
| archive_status | text |
Sign up free to try it on a real business scenario