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
Recommendations treat a track as sticky for a listener when they come back to it on a different day. Playing it three times in one evening is one sitting, not a habit.
Return one row per listener and track they returned to, ordered by listening_days descending.
Result columns · in this order
user_id | The listener. |
track_id | The track they returned to. |
title | Its title. |
listening_days | Distinct days they played it on. |
plays | Total plays, which can exceed the day count. |
How to approach it
Decide what one unit of 'coming back' is before you choose what to count.
Sample input
| 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.
| track_id | title | artist | genre | duration_ms |
|---|---|---|---|---|
| t1 | Northern Lights | Aurora Ridge | indie | 210000 |
| t2 | Paper Boats | Aurora Ridge | indie | 180000 |
| t3 | Static Bloom | Kite Machine | electronic | 240000 |
| t4 | Night Signal | Kite Machine | electronic | 195000 |
| t5 | Slow Harbour | Marisol | jazz | 300000 |
| t6 | Blue Hour | Marisol | jazz | 270000 |
| t7 | Copper Wire | Fenpost | rock | 225000 |
| t8 | Ash and Ember | Fenpost | rock | 250000 |
| t9 | Glass Field | Aurora Ridge | indie | 200000 |
| t10 | Quiet Riot Hour | Kite Machine | electronic | 165000 |
10 rows — all rows shown.
Expected output
| user_id | track_id | title | listening_days | plays |
|---|---|---|---|---|
| u3 | t5 | Slow Harbour | 3 | 3 |
| u3 | t6 | Blue Hour | 3 | 3 |
| u1 | t1 | Northern Lights | 2 | 3 |
| u1 | t9 | Glass Field | 2 | 2 |
| u2 | t3 | Static Bloom | 2 | 3 |
| u2 | t4 | Night Signal | 2 | 2 |
| u4 | t7 | Copper Wire | 2 | 2 |
| u4 | t8 | Ash and Ember | 2 | 2 |
| u6 | t2 | Paper Boats | 2 | 2 |
9 rows — all rows shown.
Constraints
listening_days counts distinct days; plays counts rows. They differ whenever a listener repeated a track within one day.COUNT(*) >= 2 is the wrong test — it accepts two plays four minutes apart.date(played_at); the time of day is irrelevant.HAVING.listening_days descending, then user_id, then track_id.Worked example
u2 played Static Bloom twice on 6 January and again on 11 February: 3 plays across 2 days, so the pair qualifies with listening_days 2 and plays 3.
u8 played Quiet Riot Hour twice on 20 March, four minutes apart, and never again. Filter on COUNT(*) >= 2 and u8 joins the list, reporting a habit that was really one evening. Counting distinct days correctly leaves them out.
What this tests
Choosing the counting unit — COUNT(*) against COUNT(DISTINCT date(...)) — and placing the test in HAVING because it is a property of the group, not the row.
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.