Stripe MRR SQL Query: Sigma, Data Pipeline & Fivetran
For founders who bill with Stripe and want MRR they can rebuild and slice themselves. You get a 12-line Sigma query for current MRR, a monthly trend, the new/expansion/churn split, and the same numbers from Stripe Data Pipeline and Fivetran.
· AI2SQL
- Stripe Sigma
- Stripe Data Pipeline
- Fivetran
- Airbyte
Quick answer
Current MRR per currency, straight from Stripe’s MRR change log. Paste it into the Sigma editor.
-- Stripe Sigma (Trino)
-- Current MRR per currency, in major units (dollars, euros)
select
currency,
sum(mrr_change) / 100.0 as mrr
from subscription_item_change_events_v2_beta
group by currency
order by mrr desc
Every row in subscription_item_change_events_v2_beta is a change to one subscription item’s MRR: a start, an end, an upgrade or a downgrade. Add up every change and you get MRR today.
Schema assumptions
| Source | Tables used | Notes |
|---|---|---|
| Stripe Sigma | subscription_item_change_events_v2_beta (event_timestamp, local_event_timestamp, currency, mrr_change, quantity_change, event_type, customer_id, subscription_id, subscription_item_id, product_id, price_id), products (id, name), customers (id, email) | mrr_change is in minor units. event_type is ACTIVE_START, ACTIVE_END, ACTIVE_UPGRADE, ACTIVE_DOWNGRADE, ACTIVE_QUANTITY_INCREASE or ACTIVE_QUANTITY_DECREASE. |
| Stripe Data Pipeline | Same tables under schema STRIPE (test data in STRIPE_TESTMODE) | Snowflake, Redshift, BigQuery or Databricks. Amounts in minor units. |
| Fivetran | subscription_history (id, status, _fivetran_active), invoice (id, status, created), invoice_line_item (invoice_id, subscription_id, subscription_item_id, price_id, amount, currency, type, proration), price (id, recurring_interval, recurring_interval_count) | No change-events table. subscription_history exists on connections created after 1 Feb 2022; older ones have subscription. |
| Airbyte | subscriptions, subscription_items, invoices, invoice_line_items | API-shaped: customer and subscription instead of *_id, Unix-epoch integer timestamps, price and period as JSON. |
Copy-ready SQL
1. MRR by month
Ending MRR for each month in which something changed. Change: nothing, except dividing by 1 instead of 100 for zero-decimal currencies.
-- Stripe Sigma (Trino)
with monthly as (
select
date_trunc('month', local_event_timestamp) as month,
currency,
sum(mrr_change) as mrr_change
from subscription_item_change_events_v2_beta
group by 1, 2
)
select
month,
currency,
sum(mrr_change) over (partition by currency order by month) / 100.0 as ending_mrr
from monthly
order by month desc, currency
Example output (made-up data):
| month | currency | ending_mrr |
|---|---|---|
| 2026-09-01 | usd | 18420.00 |
| 2026-08-01 | usd | 17150.00 |
| 2026-07-01 | usd | 16380.00 |
2. New, expansion, contraction and churned MRR by month
The MRR bridge investors ask for. This version classifies each subscription item’s event. Stripe’s full template (Sigma sidebar → Subscriptions) classifies per customer instead, so a plan switch shows as expansion there rather than churn plus new here.
-- Stripe Sigma (Trino)
select
date_trunc('month', local_event_timestamp) as month,
currency,
sum(case when event_type = 'ACTIVE_START' then mrr_change else 0 end) / 100.0 as new_mrr,
sum(case when event_type = 'ACTIVE_UPGRADE' then mrr_change else 0 end) / 100.0 as expansion_mrr,
sum(case when event_type = 'ACTIVE_DOWNGRADE' then mrr_change else 0 end) / 100.0 as contraction_mrr,
sum(case when event_type = 'ACTIVE_END' then mrr_change else 0 end) / 100.0 as churned_mrr,
sum(mrr_change) / 100.0 as net_new_mrr
from subscription_item_change_events_v2_beta
group by 1, 2
order by 1 desc, 2
Example output (made-up data):
| month | currency | new_mrr | expansion_mrr | contraction_mrr | churned_mrr | net_new_mrr |
|---|---|---|---|---|---|---|
| 2026-09-01 | usd | 1490.00 | 380.00 | -120.00 | -480.00 | 1270.00 |
| 2026-08-01 | usd | 1210.00 | 150.00 | -60.00 | -530.00 | 770.00 |
3. MRR by product
Which product carries the business. Change: nothing.
-- Stripe Sigma (Trino)
select
p.name as product,
e.currency,
sum(e.mrr_change) / 100.0 as mrr
from subscription_item_change_events_v2_beta e
join products p on p.id = e.product_id
group by 1, 2
having sum(e.mrr_change) > 0
order by mrr desc
Example output (made-up data):
| product | currency | mrr |
|---|---|---|
| Pro | usd | 12600.00 |
| Team | usd | 5820.00 |
4. Top customers by MRR
Your biggest accounts, and how concentrated revenue is. Change: the limit.
-- Stripe Sigma (Trino)
select
c.email,
e.currency,
sum(e.mrr_change) / 100.0 as mrr
from subscription_item_change_events_v2_beta e
join customers c on c.id = e.customer_id
group by 1, 2
having sum(e.mrr_change) > 0
order by mrr desc
limit 20
Example output (made-up data):
| currency | mrr | |
|---|---|---|
| ops@acme.example | usd | 990.00 |
| finance@globex.example | usd | 490.00 |
5. MRR by month in Stripe Data Pipeline (Snowflake)
Same logic as query 1, run in your warehouse. Change: stripe to your Data Pipeline database and schema, for example stripe_db.stripe.
-- Snowflake (Stripe Data Pipeline)
with monthly as (
select
date_trunc('month', local_event_timestamp) as month,
currency,
sum(mrr_change) as mrr_change
from stripe.subscription_item_change_events_v2_beta
group by 1, 2
)
select
month,
currency,
sum(mrr_change) over (partition by currency order by month) / 100 as ending_mrr
from monthly
order by month desc, currency;
6. Current MRR from Fivetran tables (Postgres)
Fivetran has no MRR change log, so build MRR from what each active subscription last paid for: the latest paid, non-proration subscription line per subscription item, normalised to a month by the price interval. Change: the stripe schema name.
-- PostgreSQL (Fivetran Stripe schema "stripe")
with active as (
select id
from stripe.subscription_history
where _fivetran_active
and status in ('active', 'past_due')
),
latest_line as (
select distinct on (li.subscription_item_id)
li.currency, li.amount, p.recurring_interval, p.recurring_interval_count
from stripe.invoice_line_item li
join stripe.invoice i on i.id = li.invoice_id
join stripe.price p on p.id = li.price_id
join active a on a.id = li.subscription_id
where li.type = 'subscription'
and not li.proration
and i.status = 'paid'
order by li.subscription_item_id, i.created desc
)
select
currency,
round(sum(
amount * case recurring_interval
when 'month' then 1.0
when 'year' then 1.0 / 12
when 'week' then 52.0 / 12
when 'day' then 365.0 / 12
end / recurring_interval_count
) / 100, 2) as mrr
from latest_line
group by currency
order by mrr desc;
Example output (made-up data):
| currency | mrr |
|---|---|
| usd | 18310.42 |
| eur | 2150.00 |
This runs high if you discount at the invoice level, because line amount is before invoice coupons. On Snowflake or BigQuery, replace distinct on with qualify row_number() over (partition by li.subscription_item_id order by i.created desc) = 1.
Run it on your own database with AI2SQL
If Fivetran or Airbyte syncs your Stripe data into Postgres, MySQL or SQL Server, connect that database read-only and ask in plain English. For Sigma, Snowflake or BigQuery, AI2SQL writes the query in that dialect and you run it there.
Free to try. See pricing for what each plan includes.
Want to run this on your database — with your real tables?
Save & run on your database →Common mistakes
- Cents, not dollars. Every Stripe amount, including mrr_change, is in the currency's minor unit. Divide by 100 for USD or EUR. Zero-decimal currencies such as JPY are already whole units, so group by currency before you divide.
- Trials counted as MRR. A trialing subscription has not paid anything. The change-events table leaves trials out, but a hand-rolled query on subscriptions or Fivetran's subscription_history must filter status to active and past_due.
- Annual plans counted at full price. A $1,200/year plan is $100 of MRR. Divide by 12 for interval = year, and by recurring_interval_count for plans billed every 3 or 6 months.
- Discounts ignored. Invoice line amounts are before invoice-level coupons. If you give large discounts, MRR from line items runs high. Stripe's change-events table already applies discounts.
- Wrong timezone. local_event_timestamp is in your Stripe account's timezone and event_timestamp is UTC. Fivetran stores Stripe timestamps in the account timezone too. Pick one and use it everywhere, or month boundaries drift.
- Test mode mixed in. Stripe Data Pipeline delivers test data to a separate schema (STRIPE_TESTMODE), and Fivetran has a separate Stripe Test Mode connector. Make sure your query points at live data.
Frequently asked questions
Which Stripe table should I use for MRR in Sigma? + −
subscription_item_change_events_v2_beta. Each row is a change to one subscription item, and mrr_change is its effect on MRR in minor units. Summing mrr_change up to a date gives MRR on that date. It replaces subscription_item_change_events and refreshes about every 3 hours in Sigma.
Why doesn't my SQL MRR match the Stripe Billing dashboard? + −
Usually one of four things: currency conversion (the dashboard converts to your default currency), timezone (local vs UTC month boundaries), very recent data (Stripe says the last two days can still change), or a different churn definition. Stripe's full template query in the Sigma sidebar reproduces the dashboard, including FX.
How do I calculate MRR from Stripe data in Snowflake or BigQuery? + −
With Stripe Data Pipeline, the same subscription_item_change_events_v2_beta table lands in your warehouse under the STRIPE schema, so the Sigma queries work with small syntax changes. With Fivetran, there is no change-events table; compute MRR from active rows in subscription_history plus their latest paid invoice lines and the price interval.
Does MRR include one-off charges or usage? + −
Not in Stripe's definition. Only recurring licensed prices contribute. One-off invoice items, setup fees and metered usage are excluded, which is why MRR is lower than monthly revenue.
Can AI2SQL connect to Stripe Sigma directly? + −
No. Sigma runs inside the Stripe Dashboard. AI2SQL can write the Sigma query for you to paste in, or connect read-only to a Postgres, MySQL or SQL Server database that Fivetran or Airbyte keeps in sync with Stripe.
Related templates
All templates: SQL templates for Stripe, Shopify and Supabase