Exclude free subscribers via anti-join
Company: Intuit
Role: Data Scientist
Category: Data Manipulation (SQL/Python)
Difficulty: medium
Interview Round: Technical Screen
Extend your previous monthly new-subscriber + YoY query to exclude companies that ever received a free subscription, using an anti-join against Free_Subs. Ensure excluded companies are removed from all months and all derived YoY metrics. Your solution should be resilient to duplicates in Free_Subs and should not accidentally re-include rows due to joins. Also, briefly explain in comments the trade-offs between using NOT EXISTS versus LEFT JOIN ... IS NULL for this anti-join under typical OLAP columnar engines.
Additional table and sample data:
Free_Subs
+------------+
| company_id |
+------------+
| 2 |
| 5 |
+------------+
Requirements:
- Do not change the output column names/types from the first question.
- The anti-join must occur before aggregation so excluded IDs do not affect zero-filled months or YoY baselines.
- Guard against duplicate company_id values in Free_Subs (e.g., use DISTINCT or NOT EXISTS).
Overview: This question evaluates competency with SQL anti-joins, join semantics, deduplication, and correct pre-aggregation filtering to prevent excluded entities from affecting aggregated monthly and year-over-year metrics; it is categorized as Data Manipulation (SQL/Python) for a Data Scientist role.
You work with a subscriptions fact table and a small months calendar. A "new subscriber" is defined as a company on the month of its first paid subscription (based on the earliest start_date in Subscriptions for that company).
Using the tables below, write a query that:
1) Computes monthly new-subscriber counts.
2) Zero-fills months using Month_Calendar so that every month in the calendar appears, even if there were no new subscribers.
3) Adds year-over-year (YoY) metrics by comparing each month to the same calendar month in the previous year.
4) Excludes any company that ever appears in Free_Subs from *all* months and *all* derived YoY metrics. The anti-join must occur **before** calculating first-subscription dates and monthly aggregations, so that excluded companies do not affect zero-filled months or YoY baselines.
5) Is resilient to duplicate company_id values in Free_Subs (i.e., your anti-join logic must not break if duplicates are present).
The final output must have exactly these columns and types:
- month_start (DATE) – first day of the month from Month_Calendar
- year (INT)
- month (INT) – numeric month (1–12)
- new_subscribers (INT) – count of companies whose first paid subscription falls in that calendar month, **excluding** companies in Free_Subs
- prev_year_new_subscribers (INT) – new_subscribers for the same month in the previous year (0 if that prior month is not present or had no new subscribers)
- yoy_abs_change (INT) – new_subscribers - prev_year_new_subscribers
- yoy_pct_change (DECIMAL(10,2)) – (new_subscribers - prev_year_new_subscribers) / prev_year_new_subscribers * 100; return NULL when prev_year_new_subscribers = 0 to avoid division by zero.
Additionally, in SQL comments within your query, briefly explain the trade-offs between using NOT EXISTS versus LEFT JOIN ... IS NULL for this anti-join under typical OLAP columnar engines (e.g., Snowflake, BigQuery, Redshift).
Tables
Subscriptions(subscription_id INT, company_id INT, start_date DATE)
Free_Subs(company_id INT)
Month_Calendar(month_start DATE, year INT, month INT)
Hints
- First compute each company’s first paid subscription date, and apply the anti-join against Free_Subs in that step before aggregating.
- Use DATE_TRUNC('month', first_paid_date) and a LEFT JOIN to Month_Calendar to ensure every month appears with zeroes where appropriate.