Holiday Promo Campaign Click Year

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
Asked in
Uber

Problem

List the months in which the HOLIDAY_PROMO campaign drew at least one click. The ad_impressions log spans several years, so a month here is a specific year and month, never the same calendar month pooled across years.

One year, the holiday campaign exploded.

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
click_month
2026-02
2026-03
2026-07

Worked solution and explanation

What this is really asking

This is a click count wearing an impression table's clothes. Every row of ad_impressions is one impression served, and a click is just clicked = 1 on that row. Anyone can filter to 'HOLIDAY_PROMO' and bucket by month. What separates candidates is the threshold: HAVING COUNT(*) >= 1 is true for every month the campaign was shown at all, so it returns all 11 served months instead of the 3 that drew a click. `SUM(clicked)` is the click count; COUNT(*) is the impression count.

Step 1: Filter the campaign early

Put ad_campaign = 'HOLIDAY_PROMO' in WHERE so other campaigns' impressions never land in a month bucket, and so a large table prunes before aggregation.

Step 2: Bucket by year and month together

The log spans several years. strftime('%Y-%m', impression_time) keeps the year in the key, so February of one year never merges with February of another. Grouping on the month alone would pool them. Repeating the expression in GROUP BY is the portable form; not every engine accepts the alias there.

Step 3: Threshold on clicks, not rows

clicked is a 0/1 flag, so SUM(clicked) per bucket is that month's click count. HAVING SUM(clicked) >= 1 keeps a month only once a real click landed in it.

`HOLIDAY_PROMO` months with a click
SELECT strftime('%Y-%m', impression_time) AS click_month
FROM ad_impressions
WHERE ad_campaign = 'HOLIDAY_PROMO'
GROUP BY strftime('%Y-%m', impression_time)
HAVING SUM(clicked) >= 1
Counting rows
HAVING COUNT(*) >= 1 asks whether the month had any impression. Every bucket that exists has at least one row, so the condition filters nothing: 11 months come back.
Summing the flag
HAVING SUM(clicked) >= 1 asks whether any impression was clicked. Months where the campaign was shown but ignored drop out, leaving the 3 that drew a click.

Common follow-up questions