runtime
57 / 88

lesson 57 Advanced product analysis · advanced

Usage cost & contribution margin

Compare usage revenue with costs to calculate contribution margin.

the idea

Contribution margin is revenue minus the variable cost of serving it. Revenue comes from cash collected (invoice payments net of refunds) in the period; usage cost is each logical event multiplied by its unit cost. Compute both at the same grain, then subtract.

Dataset: Product / SaaS Analytics

The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.

events8 columns · 135,428 rows
delivery_idnumber · unique idevent_idtextuser_idnumber · links to usersaccount_idnumber · links to accountssession_idnumber · links to sessionsevent_nametextoccurred_atdate & timereceived_atdate & time
1evt_0000001111user_signed_up2024-01-14 18:52:142024-01-14 18:52:33
2evt_0000002111onboarding_started2024-01-14 18:52:512024-01-14 18:53:06
3evt_00000846232user_signed_up2024-01-15 13:21:522024-01-15 13:22:00
4evt_00000856232onboarding_started2024-01-15 13:22:052024-01-15 13:22:16
5evt_00000866232onboarding_completed2024-01-15 13:23:522024-01-15 13:24:12
6evt_0000019119search_performed2024-01-17 20:56:552024-01-17 20:56:59
delivery_idnumber · unique id
1
event_idtext
evt_0000001
user_idnumber · links to users
1
account_idnumber · links to accounts
1
session_idnumber · links to sessions
1
event_nametext
user_signed_up
occurred_atdate & time
2024-01-14 18:52:14
received_atdate & time
2024-01-14 18:52:33
delivery_idnumber · unique id
2
event_idtext
evt_0000002
user_idnumber · links to users
1
account_idnumber · links to accounts
1
session_idnumber · links to sessions
1
event_nametext
onboarding_started
occurred_atdate & time
2024-01-14 18:52:51
received_atdate & time
2024-01-14 18:53:06
delivery_idnumber · unique id
3
event_idtext
evt_0000084
user_idnumber · links to users
6
account_idnumber · links to accounts
2
session_idnumber · links to sessions
32
event_nametext
user_signed_up
occurred_atdate & time
2024-01-15 13:21:52
received_atdate & time
2024-01-15 13:22:00
delivery_idnumber · unique id
4
event_idtext
evt_0000085
user_idnumber · links to users
6
account_idnumber · links to accounts
2
session_idnumber · links to sessions
32
event_nametext
onboarding_started
occurred_atdate & time
2024-01-15 13:22:05
received_atdate & time
2024-01-15 13:22:16
delivery_idnumber · unique id
5
event_idtext
evt_0000086
user_idnumber · links to users
6
account_idnumber · links to accounts
2
session_idnumber · links to sessions
32
event_nametext
onboarding_completed
occurred_atdate & time
2024-01-15 13:23:52
received_atdate & time
2024-01-15 13:24:12
delivery_idnumber · unique id
6
event_idtext
evt_0000019
user_idnumber · links to users
1
account_idnumber · links to accounts
1
session_idnumber · links to sessions
9
event_nametext
search_performed
occurred_atdate & time
2024-01-17 20:56:55
received_atdate & time
2024-01-17 20:56:59

first 6 of 135,428 rows · your queries use all of them

event_costs2 columns · 8 rows
event_nametext · unique idcost_microdollarsnumber
dashboard_viewed900
search_performed1500
filter_applied400
report_created12000
report_shared2500
data_exported30000
event_nametext · unique id
dashboard_viewed
cost_microdollarsnumber
900
event_nametext · unique id
search_performed
cost_microdollarsnumber
1500
event_nametext · unique id
filter_applied
cost_microdollarsnumber
400
event_nametext · unique id
report_created
cost_microdollarsnumber
12000
event_nametext · unique id
report_shared
cost_microdollarsnumber
2500
event_nametext · unique id
data_exported
cost_microdollarsnumber
30000

first 6 of 8 rows · your queries use all of them

billing_events6 columns · 4,193 rows
billing_event_idnumber · unique idaccount_idnumber · links to accountssubscription_idnumber · links to subscriptionsevent_typetextoccurred_atdate & timeamount_centsnumber
158invoice_paid2024-02-01 12:13:432900
22951invoice_paid2024-03-01 20:37:152900
358invoice_paid2024-03-02 11:47:432900
44380invoice_paid2024-03-08 15:54:2999000
5711invoice_paid2024-03-09 01:45:5899000
61117invoice_paid2024-03-20 10:01:0199000
billing_event_idnumber · unique id
1
account_idnumber · links to accounts
5
subscription_idnumber · links to subscriptions
8
event_typetext
invoice_paid
occurred_atdate & time
2024-02-01 12:13:43
amount_centsnumber
2900
billing_event_idnumber · unique id
2
account_idnumber · links to accounts
29
subscription_idnumber · links to subscriptions
51
event_typetext
invoice_paid
occurred_atdate & time
2024-03-01 20:37:15
amount_centsnumber
2900
billing_event_idnumber · unique id
3
account_idnumber · links to accounts
5
subscription_idnumber · links to subscriptions
8
event_typetext
invoice_paid
occurred_atdate & time
2024-03-02 11:47:43
amount_centsnumber
2900
billing_event_idnumber · unique id
4
account_idnumber · links to accounts
43
subscription_idnumber · links to subscriptions
80
event_typetext
invoice_paid
occurred_atdate & time
2024-03-08 15:54:29
amount_centsnumber
99000
billing_event_idnumber · unique id
5
account_idnumber · links to accounts
7
subscription_idnumber · links to subscriptions
11
event_typetext
invoice_paid
occurred_atdate & time
2024-03-09 01:45:58
amount_centsnumber
99000
billing_event_idnumber · unique id
6
account_idnumber · links to accounts
11
subscription_idnumber · links to subscriptions
17
event_typetext
invoice_paid
occurred_atdate & time
2024-03-20 10:01:01
amount_centsnumber
99000

first 6 of 4,193 rows · your queries use all of them

worked example

Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.

  1. Read the unit cost table. Run this. Each event_name maps to a cost in microdollars—the variable cost you multiply by logical event counts.the pattern

    example.sql
    SELECT event_name, cost_microdollars
    FROM event_costs
    ORDER BY cost_microdollars DESC;
  2. See May billing cash. Run this. invoice_paid and refund_issued rows show money collected in May 2025—the revenue side of margin.

    step-2.sql
    SELECT event_type, COUNT(*) AS events, SUM(amount_cents) / 100.0 AS usd
    FROM billing_events
    WHERE occurred_at >= '2025-05-01' AND occurred_at < '2025-06-01'
    GROUP BY event_type;

common mistake

Multiplying raw deliveries by unit cost charges retries twice; deduplicate events before costing them.

challenge 1

For logical events (one per event_id) that occurred in June 2025, return event_name, events and cost_usd: events × the event_costs unit cost in microdollars, converted to dollars and rounded to 2 decimals.

Include only costed event types.

what to return

Columns
event_nameeventscost_usd in this order
Rows
any order
challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.
Usage cost & contribution margin — Advanced product analysis · Runtime