Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
Finance wants to see, per country, how listening splits between the paid and free tiers — including countries where a tier has signed up and listened to nothing. stream_users holds every signed-up listener; stream_plays only holds the ones who pressed play.
Return one row per country, ordered by country.
Result columns · in this order
country | The country of the accounts. |
users | Signed-up listeners there. |
listeners | How many of them have played something. |
premium_minutes | Minutes listened by premium accounts. |
free_minutes | Minutes listened by free accounts. |
How to approach it
Drive from the table that lists everyone, and split the measure with CASE rather than two queries.
Sample input
| user_id | display_name | country | plan | signed_up_on |
|---|---|---|---|---|
| u1 | Ada Okafor | IN | premium | 2025-11-02 |
| u2 | Bo Lindqvist | US | free | 2025-11-15 |
| u3 | Cleo Martins | IN | premium | 2025-12-01 |
| u4 | Dev Rao | GB | free | 2025-12-20 |
| u5 | Esi Boateng | US | premium | 2026-01-03 |
| u6 | Fen Zhao | IN | free | 2026-01-10 |
| u7 | Gil Navarro | GB | premium | 2026-01-18 |
| u8 | Hana Sato | US | free | 2026-01-25 |
8 rows — all rows shown.
| play_id | user_id | track_id | played_at | ms_played | device |
|---|---|---|---|---|---|
| 1 | u1 | t1 | 2026-01-05 20:00:00 | 210000 | mobile |
| 2 | u1 | t2 | 2026-01-05 20:04:00 | 180000 | mobile |
| 3 | u1 | t1 | 2026-01-05 20:08:00 | 150000 | mobile |
| 4 | u1 | t9 | 2026-01-05 21:10:00 | 200000 | mobile |
| 5 | u2 | t3 | 2026-01-06 07:00:00 | 240000 | desktop |
| 6 | u2 | t4 | 2026-01-06 07:10:00 | 195000 | desktop |
| 7 | u2 | t3 | 2026-01-06 09:00:00 | 30000 | desktop |
| 8 | u3 | t5 | 2026-01-09 22:00:00 | 300000 | mobile |
| 9 | u3 | t6 | 2026-01-09 22:06:00 | 270000 | mobile |
| 10 | u3 | t5 | 2026-01-10 22:00:00 | 300000 | mobile |
| 11 | u4 | t7 | 2026-01-15 17:00:00 | 225000 | mobile |
| 12 | u4 | t8 | 2026-01-15 17:04:00 | 250000 | mobile |
| 13 | u5 | t1 | 2026-01-20 06:30:00 | 210000 | desktop |
| 14 | u5 | t3 | 2026-01-20 06:34:00 | 240000 | desktop |
| 15 | u4 | t7 | 2026-02-02 17:00:00 | 225000 | mobile |
| 16 | u1 | t1 | 2026-02-03 19:00:00 | 210000 | desktop |
| 17 | u1 | t5 | 2026-02-03 19:05:00 | 300000 | desktop |
| 18 | u5 | t5 | 2026-02-05 06:30:00 | 300000 | desktop |
| 19 | u5 | t7 | 2026-02-05 07:15:00 | 225000 | desktop |
| 20 | u2 | t10 | 2026-02-11 12:00:00 | 165000 | mobile |
| 21 | u2 | t3 | 2026-02-11 12:03:00 | 240000 | mobile |
| 22 | u3 | t6 | 2026-02-14 21:00:00 | 270000 | desktop |
| 23 | u3 | t5 | 2026-02-14 21:05:00 | 120000 | desktop |
| 24 | u6 | t2 | 2026-02-18 13:00:00 | 180000 | mobile |
| 25 | u6 | t1 | 2026-02-18 13:03:00 | 210000 | mobile |
| 26 | u5 | t2 | 2026-03-01 09:00:00 | 180000 | mobile |
| 27 | u5 | t9 | 2026-03-01 09:03:00 | 200000 | mobile |
| 28 | u1 | t9 | 2026-03-02 08:30:00 | 60000 | mobile |
| 29 | u2 | t4 | 2026-03-05 18:00:00 | 100000 | mobile |
| 30 | u3 | t6 | 2026-03-08 20:00:00 | 270000 | mobile |
| 31 | u4 | t8 | 2026-03-11 16:00:00 | 20000 | mobile |
| 32 | u6 | t2 | 2026-03-15 13:00:00 | 90000 | mobile |
| 33 | u8 | t10 | 2026-03-20 11:00:00 | 165000 | mobile |
| 34 | u8 | t4 | 2026-03-20 11:03:00 | 195000 | mobile |
| 35 | u8 | t10 | 2026-03-20 11:04:00 | 165000 | mobile |
| 36 | u8 | t9 | 2026-03-20 11:07:00 | 200000 | mobile |
36 rows — scroll inside the table to see them all.
Expected output
| country | users | listeners | premium_minutes | free_minutes |
|---|---|---|---|---|
| GB | 2 | 1 | 0 | 12 |
| IN | 3 | 3 | 47.3 | 8 |
| US | 3 | 3 | 22.6 | 28.3 |
3 rows — all rows shown.
Constraints
users counts signed-up listeners. listeners counts only those with at least one play — GB has 2 users and 1 listener.premium_minutes and free_minutes split the same listening time by the listener's plan, each rounded to 1 decimal place.0.0, not NULL.country.Worked example
GB has two signed-up listeners: u4 on the free tier with 12.0 minutes, and u7 on premium who has never pressed play. The row reads GB, 2 users, 1 listener, 0.0 premium minutes, 12.0 free minutes.
Start the query from stream_plays with an inner join and u7 vanishes. GB then reports 1 user, and premium looks like a tier nobody in Britain has bought.
What this tests
Preserving rows that have no match with a LEFT JOIN, and pivoting a column into side-by-side measures with conditional aggregation instead of running two queries and stitching them together.
Submit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.