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

ad_impressions: 10 of 200 rows
impression_iduser_idad_campaignimpression_timeclickedrevenue
253100BRAND_AWARENESS_Q12026-02-02 01:07:000NULL
306197PRODUCT_LAUNCH_X2026-03-03 02:14:000NULL
359294RETARGETING_CART2026-04-04 03:21:000NULL
412391HOLIDAY_PROMO2026-05-05 04:28:000NULL
465488NEW_USER_ACQU2026-06-06 05:35:0010.2
518NULLLOYALTY_PROGRAM2026-07-07 06:42:000NULL
571682FLASH_SALE_48H2026-08-08 07:49:000NULL
624779SUMMER_SALE_20242026-09-09 08:56:000NULL
677876BRAND_AWARENESS_Q12026-01-10 09:03:000NULL
730973PRODUCT_LAUNCH_X2026-02-11 10:10:0010.35

Expected output

First 3 of 3 rows
ad_campaignclick_revenue
FLASH_SALE_48H5.6
LOYALTY_PROGRAM214.4
SUMMER_SALE_202416.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.

Attributed click revenue above five dollars
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 > 5 keeps 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) > 5 lets many small clicks add up first, then judges the campaign by its total. That is what the review actually asks.

Common follow-up questions