Best Day for Ad Revenue
A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- medium
- Seniority
- L5
- Asked in
- Forbes
Problem
Only a clicked impression in ad_impressions records revenue: one nobody clicked earned us nothing, even though its revenue is left blank. Lay out each day of the month with its revenue per impression, its revenue per click and its biggest single-impression revenue, the days earning the most per impression first.
Some days of the month convert far better than others.
Tables
ad_impressions
Columns: impression_id INTEGER, user_id INTEGER, ad_campaign TEXT, impression_time TEXT, clicked INTEGER, revenue REAL
| impression_id | user_id | ad_campaign | impression_time | clicked | revenue |
|---|---|---|---|---|---|
| 253 | 100 | BRAND_AWARENESS_Q1 | 2026-02-02 01:07:00 | 0 | NULL |
| 306 | 197 | PRODUCT_LAUNCH_X | 2026-03-03 02:14:00 | 0 | NULL |
| 359 | 294 | RETARGETING_CART | 2026-04-04 03:21:00 | 0 | NULL |
| 412 | 391 | HOLIDAY_PROMO | 2026-05-05 04:28:00 | 0 | NULL |
| 465 | 488 | NEW_USER_ACQU | 2026-06-06 05:35:00 | 1 | 0.2 |
| 518 | NULL | LOYALTY_PROGRAM | 2026-07-07 06:42:00 | 0 | NULL |
| 571 | 682 | FLASH_SALE_48H | 2026-08-08 07:49:00 | 0 | NULL |
| 624 | 779 | SUMMER_SALE_2024 | 2026-09-09 08:56:00 | 0 | NULL |
| 677 | 876 | BRAND_AWARENESS_Q1 | 2026-01-10 09:03:00 | 0 | NULL |
| 730 | 973 | PRODUCT_LAUNCH_X | 2026-02-11 10:10:00 | 1 | 0.35 |
Expected output
| day_of_month | revenue_per_impression | revenue_per_click | max_revenue |
|---|---|---|---|
| 15 | 2.9256944444444444 | 3.052898550724638 | 4.5 |
| 7 | 0.8916666666666666 | 2.675 | 2.75 |
| 17 | 0.7625 | 3.05 | 3.05 |
| 18 | 0.7 | 1.4 | 1.4 |
| 8 | 0.6666666666666666 | 2 | 2.9 |
Worked solution and explanation
What this is really asking
This is a denominator question dressed up as a calendar report. The revenue column is filled only on clicked rows; every unclicked impression carries a blank. AVG(revenue) skips blanks, so it quietly divides by clicks, not impressions, and hands you revenue per click under a revenue-per-impression label. Anyone can bucket by day. What separates candidates is reading that blank as zero earned, folding it back in as a 0, and keeping the per-click figure as its own column. Miss it and every day's per-impression number is inflated by its click rate, zero-click days come back blank, and the day order follows click value instead of what an impression actually earns.
Step 1: Bucket by day of the month
strftime('%d', impression_time) pulls the two-digit day, and the CAST to INTEGER makes 1 through 31 compare as numbers instead of text. Every 5th of every month in every year lands in the same bucket.
Step 2: Let the raw column give the per-click view
Because only clicks carry revenue, AVG(revenue) over the bucket is exactly revenue per click, and MAX(revenue) is the biggest single impression. Both are correct as written; the blanks are supposed to drop out here.
Step 3: Put the unclicked impressions back in the denominator
AVG(CASE WHEN clicked = 1 THEN revenue ELSE 0 END) gives every unclicked row a 0 instead of a blank, so the average divides by every impression in the day. The ELSE 0 is the whole point: it is the one branch that turns 'missing' into 'earned nothing'.
Step 4: Sort on the per-impression figure
ORDER BY revenue_per_impression DESC puts the days where an impression earns the most on top. Days with no clicks sit at 0 at the bottom, which is the honest answer.
The solution
SELECT
CAST(strftime('%d', impression_time) AS INTEGER) AS day_of_month,
AVG(CASE WHEN clicked = 1 THEN revenue ELSE 0 END) AS revenue_per_impression,
AVG(revenue) AS revenue_per_click,
MAX(revenue) AS max_revenue
FROM ad_impressions
GROUP BY day_of_month
ORDER BY revenue_per_impression DESC- Averaging the column as stored
AVG(revenue)for revenue per impression divides by the clicked rows only. It returns the same number asrevenue_per_click, so you ship two columns that say one thing, and a day with no clicks showsNULL.- Counting blanks as zero
AVG(CASE WHEN clicked = 1 THEN revenue ELSE 0 END)divides by every impression. A day with 2 clicks out of 8 impressions reports a quarter of its per-click value, and a zero-click day reports 0.
Common follow-up questions
Common follow-up questions
- How would you add the click-through rate for each day? (`AVG(CASE WHEN clicked = 1 THEN 1.0 ELSE 0 END)`; per-impression revenue is then per-click revenue times that rate.)
- What if `revenue` could also be blank on a clicked impression because of a tracking gap? (Then a blank no longer means zero; you would need to tell the two cases apart before choosing a denominator.)
- How would you split this by `ad_campaign`? (Add it to the grouping; the per-impression logic is unchanged.)