Click Revenue
An easy SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.
- Domain
- SQL
- Difficulty
- easy
- Seniority
- L3
Problem
An analyst reconciling the monthly campaign review found click revenue in ad_impressions booked against impressions with no user attached, and finance refuses to credit that money to any campaign. Total each campaign's click revenue from user-attributed impressions only, keeping just the campaigns that bring in more than five dollars.
Which campaigns are earning their keep?
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
| ad_campaign | click_revenue |
|---|---|
| FLASH_SALE_48H | 5.6 |
| LOYALTY_PROGRAM | 214.4 |
| SUMMER_SALE_2024 | 16.7 |
Worked solution and explanation
Two filters wearing one costume
This is a row filter and a group filter dressed up as an ROI review. Anyone can write the SUM. What separates candidates is knowing which condition belongs to a single impression and which belongs to a whole campaign. Unattributed revenue is a fact about one row, so it goes in WHERE. The five-dollar bar is a fact about a total, so it goes in HAVING. Swap them and you either credit money finance rejects or delete every click from the report.
Step 1: Drop impressions with no user
Keep only rows where user_id is not null. An impression nobody can tie to a person may still carry revenue, and leaving it in quietly inflates the campaign it sits under.
Step 2: Total per campaign
GROUP BY ad_campaign with SUM(revenue) gives one attributed total per campaign. No click filter needed: non-clicked impressions hold NULL revenue and SUM skips them.
Step 3: Cut on the total
HAVING SUM(revenue) > 5 runs after the totals exist and drops the campaigns that did not clear the bar. This is the only place an aggregate is allowed in a predicate.
SELECT ad_campaign, SUM(revenue) AS click_revenue
FROM ad_impressions
WHERE user_id IS NOT NULL
GROUP BY ad_campaign
HAVING SUM(revenue) > 5- Cutoff on the row
WHERE revenue > 5keeps only impressions worth more than five dollars on their own. Single clicks are worth cents, so the report comes back empty.- Cutoff on the group
HAVING SUM(revenue) > 5lets many small clicks add up first, then judges the campaign by its total. That is what the review actually asks.
Common follow-up questions
- What if `revenue` could be negative because of refunds? (Whether netting refunds into the total is right for an ROI review, or whether they belong in a separate column.)
- How would you show unattributed revenue next to attributed revenue in one row per campaign? (Conditional aggregation over `user_id` inside a single `GROUP BY`.)
- What if the cutoff were relative, like campaigns above the median total? (Comparing each group to a statistic computed over all groups.)