cswork / libraryOpen practice workspace

Coding questions · Intuit

Compute monthly signups, conversion, and YoY growth

This question evaluates a candidate's ability to perform data manipulation and time-series aggregation to compute monthly signups, subscription conversion rates, and year-over-year growth from user-level tables using SQL or Python (Data Manipulation (SQL/Python)).

You work at a subscription company and are given a user-level table.

Table

company_users

  • id (INT, PK) — user/customer id
  • signup_date (DATE) — date the user signed up (created an account)
  • subscription_date (DATE, NULL) — date the user first started a subscription (NULL if never subscribed)
  • termination_date (DATE, NULL) — date the subscription ended (NULL if still active)
  • subscription_type (VARCHAR) — 'free' or 'paid' (assume this reflects the first subscription started)

Assumptions:

  • Dates are in UTC.
  • A “subscription” means subscription_date IS NOT NULL.
  • “Conversion rate by month” is defined as: for users who signed up in a given calendar month, the fraction who ever subscribed (at any later time).
  • Report results for months starting 2017-01-01 (inclusive).

Tasks

  1. For each calendar month (by signup_date month), return:
    • month (e.g., 2017-01-01 for Jan 2017)
    • signups (count of users who signed up that month)
    • subscribers (count of those signups who ever subscribed)
    • conversion_rate = subscribers / signups
  2. Compute YoY subscription rate growth for each month as:
    • yoy_subscription_rate_growth = conversion_rate−conversion_rate_same_month_last_yearconversion_rate_same_month_last_year\frac{conversion\_rate - conversion\_rate\_{same\_month\_last\_year}}{conversion\_rate\_{same\_month\_last\_year}}
    • Return NULL if the prior-year month is not available.
  3. Now assume the dataset also includes free subscriptions (subscription_type='free'). Recompute (2) but only for paid subscriptions (i.e., treat a user as “subscribed” only if subscription_type='paid').

Output

A monthly table with columns:

  • month, signups, subscribers, conversion_rate, yoy_subscription_rate_growth

(And a paid-only version for task #3.)

Monthly signups, conversion rate, and YoY conversion-rate growth (all subscriptions)

You are given a companies table (signups) and a subscriptions table (who converted). Starting from 2017-01-01 (inclusive), compute monthly metrics by signup month:

  • signups: number of companies that signed up in the month

  • conversions: number of those companies that have a subscription of any plan type (free or paid)

  • conversion_rate: conversions / signups

  • yoy_conversion_rate_growth: the year-over-year growth of conversion_rate vs the same calendar month in the prior year, computed as:

    (conversion_rate - prior_year_conversion_rate) / prior_year_conversion_rate

Return one row per signup month that exists in the data. If there is no prior-year month to compare, return NULL for yoy_conversion_rate_growth.

Output columns: month_start, signups, conversions, conversion_rate, yoy_conversion_rate_growth.

Round rates/growth to 4 decimal places.

Table companies

columntypeconstraints
company_idINTPRIMARY KEY
signup_dateDATENOT NULL

Sample data:

company_idsignup_date
12017-01-05
22017-01-10
32017-01-15
42017-02-02
52017-02-10
62017-02-25
132017-03-12
142017-03-20
72018-01-03
82018-01-20
92018-02-05
102018-02-18
112018-02-20
122018-03-01
152018-03-10
162018-03-22

Table subscriptions

columntypeconstraints
subscription_idINTPRIMARY KEY
company_idINTNOT NULL
start_dateDATENOT NULL
plan_typeVARCHAR(10)NOT NULL
termination_dateDATE

Sample data:

company_idplan_typestart_datesubscription_idtermination_date
1paid2017-01-20101NULL
3free2017-02-01103NULL
4paid2017-02-151042017-12-31
5free2017-02-28105NULL
14paid2017-04-01114NULL
7paid2018-01-25107NULL
8free2018-02-10108NULL
9paid2018-02-20109NULL
11paid2018-03-05111NULL
12free2018-03-15112NULL
15paid2018-03-28115NULL

Expected output

One row per signup month with counts and rates for all subscriptions (free + paid). month_start is the first day of the month.

conversion_rateconversionsmonth_startsignupsyoy_conversion_rate_growth
0.666722017-01-013NULL
0.666722017-02-013NULL
0.512017-03-012NULL
122018-01-0120.4999
0.666722018-02-0130
0.666722018-03-0130.3334

Hints

  1. Compute monthly signups first, then join the monthly result to itself shifted by 1 year.
  2. Use NULLIF to avoid division-by-zero and return NULL when prior-year data is missing.

Monthly signups and YoY growth for paid-only conversion rate

Using the same tables, compute the same monthly metrics starting from 2017-01-01 (inclusive), but only count conversions where the company has a PAID subscription (plan_type = 'paid').

  • signups: companies signed up in that month

  • paid_conversions: those signups that have a paid subscription

  • paid_conversion_rate: paid_conversions / signups

  • yoy_paid_conversion_rate_growth: year-over-year growth of paid_conversion_rate vs the same month in the prior year:

    (paid_conversion_rate - prior_year_paid_conversion_rate) / prior_year_paid_conversion_rate

Return one row per signup month that exists in the data. Round rates/growth to 4 decimals.

Output columns: month_start, signups, paid_conversions, paid_conversion_rate, yoy_paid_conversion_rate_growth.

Table companies

columntypeconstraints
company_idINTPRIMARY KEY
signup_dateDATENOT NULL

Sample data:

company_idsignup_date
12017-01-05
22017-01-10
32017-01-15
42017-02-02
52017-02-10
62017-02-25
132017-03-12
142017-03-20
72018-01-03
82018-01-20
92018-02-05
102018-02-18
112018-02-20
122018-03-01
152018-03-10
162018-03-22

Table subscriptions

columntypeconstraints
subscription_idINTPRIMARY KEY
company_idINTNOT NULL
start_dateDATENOT NULL
plan_typeVARCHAR(10)NOT NULL
termination_dateDATE

Sample data:

company_idplan_typestart_datesubscription_idtermination_date
1paid2017-01-20101NULL
3free2017-02-01103NULL
4paid2017-02-151042017-12-31
5free2017-02-28105NULL
14paid2017-04-01114NULL
7paid2018-01-25107NULL
8free2018-02-10108NULL
9paid2018-02-20109NULL
11paid2018-03-05111NULL
12free2018-03-15112NULL
15paid2018-03-28115NULL

Expected output

One row per signup month with paid-only conversion rate and YoY growth (vs the same month in the prior year).

month_startpaid_conversion_ratepaid_conversionssignupsyoy_paid_conversion_rate_growth
2017-01-010.333313NULL
2017-02-010.333313NULL
2017-03-010.512NULL
2018-01-010.5120.5
2018-02-010.6667231
2018-03-010.333313-0.3333

Hints

  1. Filter paid subscriptions in the JOIN condition so signups with no paid conversion are still kept.
  2. Self-join the monthly aggregate on (month_start - interval '1 year') to compute YoY.

Pivot daily users and revenue by platform (web vs mobile)

You are given a purchases table with one row per purchase event.

For each file_date, compute:

  • distinct purchasers and total revenue on web
  • distinct purchasers and total revenue on mobile

Return one row per day with the following columns:

  • day
  • web_total_users
  • web_total_revenue
  • mobile_total_users
  • mobile_total_revenue

If a platform has no purchases on a given day, return 0 for its totals.

This is a pivot-style output: one row per day, platforms as columns.

Table purchases

columntypeconstraints
file_dateDATENOT NULL
user_idINTNOT NULL
skuVARCHAR(10)NOT NULL
priceDECIMAL(10,2)NOT NULL
channelVARCHAR(20)NOT NULL
customer_segmentVARCHAR(20)NOT NULL
platformVARCHAR(10)NOT NULL

Sample data:

channelcustomer_segmentfile_dateplatformpriceskuuser_id
seoalpha2024-01-01web57A123
brandbeta2024-01-01web59B765
seoalpha2024-01-01web10E123
appgamma2024-01-01mobile20M111
tvalpha2024-01-07mobile100C943
seobeta2024-01-07web30F222
radiogamma2024-01-09mobile103A587
tvalpha2024-01-11web102D976
brandalpha2024-01-11mobile50G333

Expected output

One row per day with platform totals pivoted into columns.

daymobile_total_revenuemobile_total_usersweb_total_revenueweb_total_users
2024-01-012011262
2024-01-071001301
2024-01-09103100
2024-01-115011021

Hints

  1. Use conditional aggregation (CASE WHEN) to pivot platform values into columns.
  2. Count distinct user_id per platform to get total users, and sum price for revenue.