The Widest Net

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
L4
Asked in
Travelport

Problem

Find each campaign's true reach from ad_impressions: how many different registered users clicked at least one of its ads, counting a person once however many times they clicked. The analyst building the campaign scorecard reads it widest-reaching first.

Not the clicks. The crowd: how many people each campaign actually pulled in.

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

users

Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT

users: 10 of 200 rows
user_idusernameemailsignup_dateaccount_statusage_bucket
100alicealice@example.com2025-02-02inactive25-34
197aaron42aaron42@example.com2026-03-03suspended35-44
294 ameliaamelia@example.com2024-04-04pending_verification45-54
391arjun arjun@example.com2025-05-05active55-64
488ava99ava99@example.com2026-06-06inactive65+
585andrew_kandrew_k@example.com2024-07-07suspendedNULL
682anikaanika@example.com2025-08-08 16:34:00pending_verification18-24
779aidenaiden@example.com2026-09-09 14:53:00active25-34
876aria_baria_b@example.com2024-10-10inactive35-44
973brianbrian@example.com2025-11-11suspended45-54

Expected output

First 5 of 8 rows
ad_campaignusers_reached
LOYALTY_PROGRAM13
SUMMER_SALE_20246
RETARGETING_CART1
PRODUCT_LAUNCH_X1
NEW_USER_ACQU1

Worked solution and explanation

What this really asks

This is a count of different people dressed up as a campaign scorecard. Anyone can group ad_impressions by ad_campaign. What separates candidates is where the click condition and the per-person collapse land. Reach is how many different users clicked, so two things have to happen to user_id inside the same count: unclicked impressions drop out, and a person who clicked ten times counts once. Count click rows and LOYALTY_PROGRAM reports 71 instead of 13. Count different users without the click condition and you have measured who saw the ads, not who acted on them.

Counting click events
COUNT(*) or SUM(clicked) over clicked rows counts events. On this data LOYALTY_PROGRAM has 71 clicked impressions because the same monthly clickers come back year after year, so the campaign looks more than five times wider than it is.
Counting different clickers
COUNT(DISTINCT ...) over the clicking user_id collapses each person's repeat clicks. Those 71 rows come from 13 different users (one click carries no user at all), so reach is 13.

Building it

Step 1: Make the click condition part of the count

Group ad_impressions by ad_campaign and count CASE WHEN clicked = 1 THEN user_id END. A clicked row hands its user_id to the count; an unclicked row hands it NULL, which the count skips. Drop the CASE and the same query counts every viewer: exposure, not reach.

Step 2: Collapse repeat clickers with DISTINCT

COUNT(DISTINCT ...) keeps one entry per person per campaign. SUMMER_SALE_2024 has 7 clicked impressions from 6 people, and the gap is far wider wherever a regular keeps clicking. Anonymous clicks with a NULL user_id fall out for free, which is what 'registered users' asks for.

Step 3: Put the widest reach first

Sort by users_reached descending. Six campaigns tie at one clicker each. Nothing in the ask orders them against each other, so any order among them is correct.


The solution

Reach as different clicking users per campaign
SELECT ai.ad_campaign,
       COUNT(DISTINCT CASE WHEN ai.clicked = 1 THEN ai.user_id END) AS users_reached
FROM ad_impressions ai
GROUP BY ai.ad_campaign
ORDER BY users_reached DESC

Common follow-up questions