Learn SQL/Intermediate/Grouping & Aggregation/SQL Conditional Aggregation

SQL Conditional Aggregation

Aggregate only rows matching a condition, WITHIN each group, using CASE inside the aggregate — the classic technique for splitting one column into several conditional columns.

What & Why

Conditional aggregation places a CASE WHEN expression inside an aggregate so one grouped query can calculate metrics for different subsets of the same rows.

COUNT(CASE WHEN qualified_at IS NOT NULL THEN 1 END) counts a lead only when the condition is true. Otherwise CASE returns NULL implicitly and COUNT skips it.

See How It Works

BUSINESS QUESTION

Marketing wants total, qualified, and converted leads for every acquisition source.

idcampaign_idemailcreated_atqualified_atconverted_atlead_scoresourcecountry
3011ana@example.com2024-01-21 09:10:00+002024-01-22 11:00:00+002024-02-02 10:00:00+0086google_adsUS
3021ben@example.com2024-01-24 12:40:00+00NULLNULL52google_adsCA
3032chloe@example.com2024-02-16 08:30:00+002024-02-18 14:20:00+00NULL74emailGB
3043dev@example.com2024-03-20 17:15:00+002024-03-21 09:00:00+002024-04-04 16:00:00+0091linkedinUS
Watch each marketing.leads row update its source metricsLead 1 of 4
COUNT(*) · COUNT(CASE WHEN qualified_at IS NOT NULL THEN 1 END) · COUNT(CASE WHEN converted_at IS NOT NULL THEN 1 END)
idsourcequalified_atconverted_atstate
301google_ads2024-01-22 11:00:00+002024-02-02 10:00:00+00CURRENT
302google_adsNULLNULLWAIT
303email2024-02-18 14:20:00+00NULLWAIT
304linkedin2024-03-21 09:00:00+002024-04-04 16:00:00+00WAIT
sourceleadsqualified_leadsconverted_leads
google_ads111

Lead 301 increments total, qualified, and converted for google_ads.

EXAMPLE QUERY
SELECT
  source,
  COUNT(*) AS leads,
  COUNT(CASE WHEN qualified_at IS NOT NULL THEN 1 END) AS qualified_leads,
  COUNT(CASE WHEN converted_at IS NOT NULL THEN 1 END) AS converted_leads
FROM marketing.leads
GROUP BY source
ORDER BY leads DESC, source;
Now You Try

Practice this concept

Marketing wants total, qualified, and converted lead counts for every source.

Available schema
marketing

Prefix tables with marketing.table_name.

sourceleadsqualified_leadsconverted_leads
marketing.leads
ColumnType
idinteger
campaign_idinteger
emailtext
created_attimestamp with time zone
qualified_attimestamp with time zone
converted_attimestamp with time zone
lead_scoreinteger
sourcetext
countrytext
archive_statustext
query.sql
Intermediate business practice

Sign up free to try it on a real business scenario