Weiter zum Inhalt
Konto erstellen
oder
anmelden
Das Logo der Stripe-Dokumentation
/
KI fragen
Konto erstellen
Anmelden
Jetzt starten
Zahlungen
Umsatz
Plattformen und Marktplätze
Geldmanagement
Entwicklerressourcen
Übersicht
Billing
ÜbersichtÜber die Billing APIs
Abonnements
Invoicing
Nutzungsbasierte Abrechnung
Angebote
Kundenverwaltung
Abrechnung mit anderen Produkten
Umsatzsicherung
Automatisierungen
Integration testen
Steuer
Übersicht
Stripe Tax verwenden
Compliance-Management
Berichte
Übersicht
Bericht auswählen
Berichte konfigurieren
API für Berichte
Berichte für mehrere Konten
Umsatzrealisierung
Daten
ÜbersichtSchema
Nutzerspezifische Berichte
Data Pipeline
Datenverwaltung
    Übersicht
    Anwendungsszenarien für Geschäfts- und Produktdaten
      Transaktionsdaten
      Daten zu Anfechtungen und Betrug
      Daten zu allen Gebühren
      Abrechnungsdaten
      Steuerdaten
      Daten zu verbundenen Konten
      Daten zur Kartenausstellung
    Externe Daten importieren
StartseiteUmsatzData managementBusiness and product data use cases

Rechnungsdaten abfragen

Verwenden Sie Sigma oder Data Pipeline, um Abrechnungsinformationen abzurufen.

Die Abrechnung besteht aus verschiedenen Komponenten, die zusammenarbeiten, um einmalige Rechnungen und regelmäßige Abrechnungen bereitzustellen, wobei verschiedene Aspekte der Abrechnungsdaten in einer Reihe von Tabellen verfügbar sind. Alle abrechnungsspezifischen Tabellen befinden sich im Abschnitt Abrechnung des Schemas, wobei die primären Tabellen subscriptions und invoices sind.

Um die Abrechnungsdaten genauer zu untersuchen, können Sie die zusätzlichen Tabellen verwenden, die die Komponenten von Abonnements und Rechnungen darstellen, z. B. prices, products oder coupons. Darüber hinaus ist die Tabelle customers ein wesentlicher Bestandteil der Abrechnung und enthält Daten, über die Sie möglicherweise Berichte erstellen müssen.

Abonnements

Jede Zeile in der Tabelle subscriptions liefert Daten zu einem einzelnen Subscription-Objekt – das sind die gleichen Informationen, die die API abruft oder im Stripe-Dashboard verfügbar sind. Sie können über jedes Abonnement Berichte erstellen, das Sie in Ihrem Konto erstellen.

Diese Tabelle ist der empfohlene Ausgangspunkt für die Erstellung von Berichten über Ihre aktuellen Abonnent/innen. Sie können diese Tabelle mit anderen zugehörigen Tabellen zusammenführen, sodass Sie Ihre Daten detaillierter untersuchen können.

Das folgende Beispiel ruft eine Liste von Abonnements ab, die als unbezahlt markiert wurden, sowie alle verfügbaren Kontaktinformationen für die Kundin/den Kunden.

select subscriptions.id, subscriptions.customer_id, customers.email from subscriptions inner join customers on customers.id = subscriptions.customer_id where subscriptions.status = 'unpaid' limit 5
IDcustomer_idE-Mail
sub_Ztlj6sAZn1Pl17ycus_JOSUraX8FlV3ocAjenny.rosen@example.com
sub_fADmJgLVA3VPWLCcus_nUIIEMPHH63xVNnnoah.wilson@example.com
sub_SGVY5yh6EKwN5recus_jUFaAcSMloLBYe5joshua.miller@example.com
sub_4vtEGIWNuQOi7Qtcus_ItNX6M6HCVa2DItmadison.jackson@example.com
sub_eNV9Mzn72j51gBRcus_1210dmhqVgXcGOtelijah.smith@example.com

Kund/innen

Daten über Customer-Objekte sind in der Tabelle customers enthalten (diese ist nicht Teil der Gruppe Abrechnung Tabellen). Er wird üblicherweise in abrechnungsbasierten Berichten verwendet und kann mit einer Reihe von Tabellen zusammengeführt werden. Es ist auch nützlich, wenn Sie Zahlungen mit gespeicherten Zahlungsinformationen erstellen.

Im folgenden Beispiel wird eine Liste von Kund/innen mit abonnements abgerufen, die sich derzeit im Testzeitraum befinden. Es ruft sowohl die ID als auch die E-Mail-Adresse für jede/n Kund/in ab.

select customers.id, customers.email, subscriptions.price_id from subscriptions inner join customers on customers.id = subscriptions.customer_id where subscriptions.status = 'trialing' limit 5
IDE-Mailprice_id
cus_Glyn2JdtVln4E7kjenny.rosen@example.comruby-pro-522
cus_aCUmskMojFkWeq8noah.wilson@example.comruby-pro-522
cus_gsq5hzIwS9dvAOErichard.jones@example.comgold-basic-221
cus_lk3Brq5N3SuKtFgmadison.jackson@example.comgold-basic-221
cus_2ppZ7w8Bu1POByMelijah.smith@example.comsilver-pro-498

Produkte und Preise

Produkte sind die Artikel, die Ihre Kund/innen mit einem Abonnement erwerben können. Preise sind an Produkte gebunden und umfassen Kosten, Abrechnungsintervall und Währung. Wenn Sie Daten aus der Tabelle subscriptions anzeigen, können Sie diese mit subscription_items zusammenführen. Darüber hinaus können Sie sie mit products.id zusammenführen, indem Sie die price_product_id aus dem Artikel verwenden.

Das folgende Beispiel gibt eine Liste aktiver Abonnements zusammen mit dem Produktnamen und seiner Zahlungsbeschreibung in der Abrechnung zurück:

active_subscription_products.sql
with active_subscriptions as ( select s.id as subscription_id, p.name as product_name, p.statement_descriptor from subscriptions s join subscription_items si on s.id = si.subscription_id join products p on si.price_product_id = p.id where s.status = 'active' ) select subscription_id, subscription_item_id, price_id, product_name, statement_descriptor from active_subscriptions order by 1,2
IDNamestatement_descriptor
sub_JsEi0hk65BiYYmrruby-pro-522Ruby Pro
sub_Eb9UJQMG5FORHl1gold-basic-221Gold Basic
sub_nlfMIC65IS0lxcfsilver-pro-498Silver Pro
sub_MLt62fmgWxBsRWPdiamond-mid-244Diamond Mid
sub_Ah2Ve165ZxotNS8ruby-standard-196Ruby Standard

Preisstufen

Während Sie Preise mit Stufen in Ihren Abonnements verwenden, kann die Tabelle price_tiers spezifische Daten zu jeder Stufe bereitstellen. Wenn Sie beispielsweise Informationen zur Anfangsstufe Ihrer Abonnements erhalten möchten, einschließlich der Höchstmenge für die erste Stufe und des verwendeten Betrags für Einheiten, beziehen Sie sich auf die folgende Abfrage:

tiered_prices.sql
with subscription_item_prices as ( select si.subscription_id, si.price_id, p.currency from subscription_items si join prices p on si.price_id = p.id ), price_tier_details as ( select sp.subscription_id, pt.price_id, pt.upto, stringify_amount(sp.currency, pt.amount, '.') as tier_price, sp.currency from subscription_item_prices sp join price_tiers pt on sp.price_id = pt.price_id ) select ptd.subscription_id, ptd.price_id, ptd.upto, ptd.tier_price, ptd.currency from price_tier_details ptd order by ptd.subscription_id, ptd.price_id, ptd.upto asc
subscription_idprice_iduptotier_priceWährung
sub_8voBA7uynB31Uwbprice_od8mXT7saHzJjAk302,00USD
sub_ux8JHM5sbiyj5LKprice_RkuaUI9Lk3NeAi2601,00USD
sub_bgcWjhU2F2WoSmZprice_uaDnz8LfqPBFuwg900.50USD

Rechnungen

Mit Rechnungen arbeiten

In unserer Rechnungsdokumentation finden Sie weitere Informationen zu Rechnungen, Rechnungspositionen und Rechnungsposten.

Die Tabelle invoices enthält Daten über einzelne Rechnung-Objekte. Für jedes Abonnement wird in regelmäßigen Abständen eine Rechnung erstellt, die den von der Kundin/vom Kunden geschuldeten Betrag darstellt. Dies beinhaltet automatisch den für das Abonnement erforderlichen Betrag und alle zusätzlichen Rechnungsposten, die möglicherweise erstellt wurden (aufgelistet als Einzelposten).

Rechnungen bestehen aus einzelnen (Rechnungs-)Posten. Diese Posten stellen alle Abonnements dar, die Kundinnen/Kunden in Rechnung gestellt werden, sowie Rechnungspositionen, die erstellt und auf die Rechnung angewendet wurden. Um eine Rechnung aufzuschlüsseln und jeden ihrer Posten zu analysieren, verwenden Sie die Tabelle invoice_line_items.

Die Spalte source_id dieser Tabelle enthält die ID des Abonnements (beispielsweise sub_jPGt6hFpl2hDbpG) oder der Rechnungsposition (beispielsweise ii_6rsjeFoT1KLTkQu), zu dem bzw. der der Posten gehört. Die Spalte source_type gibt an, ob der Posten ein Abonnement oder eine Rechnungsposition darstellt.

Im Gegensatz zu anderen Fremdschlüsseln wird die Spalte subscription der Tabelle invoice_line_items nicht immer ausgefüllt. Wenn die entsprechende Rechnungsposition für ein Abonnement steht, ist diese Spalte leer – ihre ID steht bereits in der Spalte source_id.

Rechnungsposten

Daten zu Rechnungsposten sind in der Tabelle invoice_items enthalten. Rechnungsposten werden üblicherweise verwendet, um einen zusätzlichen Betrag anzugeben (oder einen Betrag abzuziehen), der auf der nächsten Rechnung zu Beginn des nächsten Abrechnungszyklus angewendet wird. Sie würden beispielsweise einen Rechnungsposten erstellen, wenn Sie Ihrer Kundin/Ihrem Kunden in Rechnung stellen müssen, dass er sein monatliches Guthaben überschreitet, oder wenn Sie auf der nächsten Rechnung eine Gutschrift für nicht in Anspruch genommene Dienstleistung ausstellen müssen.

Im folgenden Beispiel werden alle Rechnungen und zugehörigen Zahlungs-IDs für ein bestimmtes Abonnement abgerufen.

select id, charge_id, amount_due from invoices where subscription_id = 'sub_ALJXL9gBYtv6GJ'
IDName
in_AtwBYHS30JWE1onch_M8U6bL7NHuJPWgA1999
in_VEjG9c4UynjCvY4ch_VtIFOVPtZOklewr1999
in_zI1bWAIv1eGqzLK1999ch_4EqaeGTrQEPFkBH
in_4G6GKl7oO1ieapc1999ch_AFyczDRkA2TqYOG
in_8dDGm1KY0aBG0Sx1999ch_VtSCgbSYV6NTkf3

Rechnungssummen und Rabatte

Die Rechnungszwischensumme ist die Summe aller Abonnements, Rechnungspositionen und Verrechnungen auf der Rechnung, bevor eventuelle Rabatte angewendet werden. Die Rechnungsgesamtsumme ist die Summe nach Anwendung von Rabatten und Steuern:

invoice.total = invoice.subtotal - discount + invoice.tax

Es gibt keine Spalte, um den Rabattbetrag auf einer Rechnung darzustellen. Stattdessen können Sie diesen berechnen, indem Sie die Rabattbeträge der Einzelposten zusammenfassen. Die folgende Abfrage gibt eine Liste der Rechnungen, das Start- und Enddatum und den gesamten Rabattbetrag für die Rechnung zurück.

invoice_discounts.sql
with invoices_with_discounts as ( select invoice_id, sum(amount) as total_discount_amount from invoice_line_item_discount_amounts group by invoice_id ) select i.id as invoice_id, i.period_start, i.period_end, stringify_amount(i.currency, ilda.total_discount_amount, '.') as total_discount_amount i.currency from invoices i join invoices_with_discounts ilda on i.id = ilda.invoice_id order by i.id
invoice_idperiod_startperiod_endtotal_discount_amountWährung
in_udggRVOkQGvHHCx01.05.202401.06.202424,66USD
in_DGYr3P21plhctu501.06.202401.07.202424,34USD
in_4Gd4LjrfGIfAVlN01.04.202401.05.202445,96USD

Mit Rechnungsdaten und -zeiträumen arbeiten

Abonnement werden im Voraus abgerechnet. Dies bedeutet, dass der Kunde/die Kundin die Zahlung zu Beginn eines Abrechnungszyklus leistet. Dies wird im Wert period eines Posten dargestellt. Die Abrechnung für einen Kunden/eine Kundin mit einem monatlichen Abonnement erfolgt beispielsweise zu Beginn eines jeden Monats. Wenn sich der Kunde/die Kundin für cancel_at_period_end entscheidet, bleibt sein/ihr Abonnement bis zum Ende des Monats aktiv. Danach endet das Abonnement.

Die Werte period_start und period_end einer Rechnung geben an, wann Rechnungsposten erstellt wurden – sie geben nicht immer genau den Zeitraum an, für den Kundinnen/Kunden eine Rechnung gestellt wird. Wenn ein Kunde/eine Kundin beispielsweise am 1. eines jeden Monats eine Rechnung erhält und am 15. sein/ihr monatliches Kontingent überschreitet, können Sie einen Rechnungsposten für alle zusätzlichen Kosten erstellen, die dem Kunden/der Kundin in Rechnung gestellt werden. Dieser Rechnungsposten ist dann in der nächsten Rechnung enthalten, die am 1. des nächsten Monats erstellt wird. Bei der nächsten Rechnung ist das Datum für period_start der 15. des Vormonats: das Datum, an dem der zusätzliche Rechnungsposten ursprünglich erstellt wurde.

Nutzungsbasierte Abrechnung

Mit der nutzungsbasierten Abrechnung können Sie Ihren Kundinnen/Kunden Gebühren basierend auf der Nutzung Ihres Produkts oder Ihrer Dienstleistung in Rechnung stellen.

Abrechnungszähler

Ein Zähler-Objekt gibt an, wie Zählerereignisse über einen Abrechnungszeitraum hinweg zusammengefasst werden. Zählerereignisse stellen alle Aktionen dar, die Kundinnen/Kunden in Ihrem System durchführen (beispielsweise API-Anfragen). Zähler sind an Preise gebunden und bilden die Grundlage für das, was in Rechnung gestellt wird. Diese Objekte sind über die Tabelle billing_meters verfügbar.

Die folgende Abfrage gibt alle aktiven Abrechnungszähler zurück.

meters.sql
select id, status, display_name, default_aggregation_formula from billing_meters where status = 'ACTIVE' and livemode
IDStatusdisplay_namedefault_aggregation_formula
mtr_klDCgg7djnevmyRAKTIValpaca_ai_tokenSUMME
mtr_um1e9DgLM1XAcYkAKTIValpaca_ai_image_tokenANZAHL

Übersichte über Abrechnungszähler-Ereignisse

Ein Objekt des Typs Übersicht über Abrechnungszähler-Ereignisse stellt eine aggregierte Ansicht der Zählerereignisse eines Kunden/einer Kundin innerhalb eines bestimmten Zeitraums dar. Es gibt an, in welchem Umfang für einen Kunden/eine Kundin Verbrauch in diesem Zeitraum anfällt. Diese Objekte sind über die Tabelle billing_meter_event_summaries verfügbar. Stündliche Zusammenfassungen sind verfügbar, wie in der Spalte value_grouping_window angegeben.

Die folgende Abfrage gibt die Summe der Abrechnungszähler-Ereignisse für einen bestimmten Kunden/eine bestimmte Kundin zurück.

billing_meter_event_summaries.sql
select billing_meters.display_name, sum(billing_meter_event_summaries.aggregated_value) AS total_usage from billing_meter_event_summaries join billing_meters on billing_meters.id = billing_meter_event_summaries.meter_id where billing_meter_event_summaries.customer_id = 'cus_EDQkYj7P2Jf3sJ1' and billing_meter_event_summaries.start_time >= timestamp '2025-02-01 08:00' and billing_meter_event_summaries.end_time <= timestamp '2025-02-01 20:00' and value_grouping_window = 'hourly' group by display_name
display_nametotal_usage
alpaca_ai_token459481
alpaca_ai_image_token75

Ungültige Abrechnungszähler-Ereignisse

Ein Objekt des Typs Ungültiges Abrechnungszähler-Ereignis stellt ein Abrechnungszähler-Ereignis dar, das nicht erfolgreich validiert wurde. Diese Objekte sind über die Tabelle billing_meter_invalid_events verfügbar. Die zugehörige Tabelle billing_meter_invalid_events_payload enthält die Ereignisnutzlast des ursprünglichen Ereignisses.

Die folgende Abfrage gibt alle ungültigen Abrechnungszähler-Ereignisse für einen bestimmten Kunden/eine bestimmte Kundin zurück.

billing_meter_invalid_events.sql
SELECT billing_meter_invalid_events.id as event_id, billing_meter_invalid_events.error_code, billing_meter_invalid_events.error_message FROM billing_meter_invalid_events JOIN billing_meter_invalid_events_payload ON billing_meter_invalid_events_payload.event_id = billing_meter_invalid_events.id WHERE billing_meter_invalid_events_payload.key = 'stripe_customer_id' AND billing_meter_invalid_events_payload.value = 'cus_EDQkYj7P2Jf3sJ1'
event_iderror_codeerror_message
Jcrr7EAGfYUenOql757BpAYKdPkIsxgJMETER_NOT_FOUNDKein Zähler gefunden, der event_name mtr_0YM3adbdKB0toMH entspricht.
2bkQWRgXTG0ExDAsZyNIcw5D2BqjOxYeMETER_NOT_FOUNDKein Zähler gefunden, der event_name mtr_RssG485hoCUkV44 entspricht.

Gutscheine

Ein Coupon-Objekt stellt einen Rabatt in Form eines Betrags oder Prozentwerts dar, den Sie auf Abonnements oder für Kundinnen/Kunden anwenden können.

coupons.sql
select coupons.id, coupons.amount_off, coupons.percent_off from coupons where valid = false limit 5
IDamount_offpercent_off
10FF10
SUMMER2525
10FREE10
15OFF15
FALL3030

Rabatte

Bei einem Rabatt handelt es sich um die Anwendung eines Gutscheins, der durch ein Discount-Objekt dargestellt wird. Mit der folgenden Abfrage wird eine Liste der Abonnements und der damit verbundenen Rabatte und Gutscheine zurückgegeben:

discounts.sql
select subscriptions.id as subscription_id, t.discount_id, coupons.id as coupon_id from subscriptions cross join unnest(split(subscriptions.discounts, ',')) as t(discount_id) join discounts on discounts.id = t.discount_id join coupons on coupons.id = discounts.coupon_id limit 3
subscription_iddiscount_idcoupon_id
sub_D2ZrvxtbYQTU6n4di_xUFdwFQG16ioP0p10OFF
sub_5Lx9Mgyam3uMHC7di_kmiHf0Tir7oHiWd25OFF
sub_4cLWcJ2CvLiqwJYdi_gNYTaTuXjgHRCqA10FREE

Promo-Codes

Ein Promo-Code stellt einen von einer Kundin/einem Kunden einlösbaren Code für einen Gutschein dar. Die folgende Abfrage enthält eine Liste der Promo-Codes für einen bestimmten Gutschein und zeigt an, wie oft jeder Code eingelöst wurde:

promotion_codes.sql
select promotion_codes.id as promotion_code_id, promotion_codes.code as promotion_code, promotion_codes.times_redeemed from promotion_codes limit 3
promotion_code_idCodetimes_redeemed
promo_LAYQGg1NNac1gzp10OFF1
promo_lWJjhuRyfm0Q7zy25OFF2
promo_sq8mQ6o1NZ31D7d10FREE3

Ereignisse bei der Änderung von Abonnement-Artikeln

Die Tabelle subscription_item_change_events verfolgt Änderungen an Abonnement-Objekten, die sich auf den monatlich wiederkehrenden Umsatz (MRR) und die Abonnementmengen auswirken. Verwenden Sie diese Tabelle, um den MRR für einzelne Kundinnen/Kunden, Produkte und Pläne zu berechnen und benutzerdefinierte Metrikdefinitionen für Ihre Geschäftsmodelle zu erstellen sowie Änderungen der Abonnementmengen zu verfolgen.

Vorsicht

Diese Tabelle enthält aktuellere Daten als die Quelle, aus der die MRR-Metriken in der Abrechnungsübersicht im Stripe Dashboard stammen. Dies bedeutet, dass die Daten für den MRR des letzten und des aktuellen Tages hier genauer sein könnten und von dem abweichen könnten, was Sie im Dashboard sehen.

local_event_timestamp and event_timestamp

Diese Tabelle enthält zwei Zeitstempelspalten:

  • event_timestamp: Dies ist der UTC-Zeitstempel.
  • local_event_timestamp: Dieser Zeitstempel befindet sich in Ihrer lokalen Zeitzone, in der Regel der Zeitzone der Person, die Ihr Stripe-Konto erstellt hat.

Währung

Hier finden Sie die Abrechnungswährung des Abonnementartikels als dreibuchstabigen ISO-Währungscode in Kleinbuchstaben. Die Währung muss eine sein, die Stripe unterstützt.

mrr_change

Die Spalte mrr_change zeigt die positiven oder negativen Auswirkungen eines Ereignisses auf Ihren MRR in der Nebeneinheit der Abrechnungswährung des Abonnements (zum Beispiel Cent für USD).

quantity_change

Die Spalte quantity_change zeigt die zugehörige positive oder negative Änderung der Menge eines Abonnement-Artikels, den eine Kundin/ein Kunde abonniert.

event_type

EreignistypDefinition
ACTIVE_STARTDer Abonnementposten hat begonnen, zum MRR beizutragen.
ACTIVE_ENDDer Abonnementposten hat aufgehört, zum MRR beizutragen.
ACTIVE_UPGRADEDer MRR-Beitrag des Abonnementartikels hat sich erhöht. Dies kann passieren, wenn der Preis eines Abonnementartikels oder die Menge dieses Abonnementartikels steigt.
ACTIVE_DOWNGRADEDer MRR-Beitrag des Abonnementartikels hat sich verringert. Dies kann passieren, wenn der Preis eines Abonnementartikels oder die Menge dieses Abonnementartikels sinkt.
ACTIVE_QUANTITY_INCREASEDie Menge des Abonnement-Artikels hat sich erhöht, der MRR ist hiervon jedoch nicht betroffen. Dies kann passieren, wenn Sie eine gestaffelte Preisgestaltung verwenden und die Menge über einem bestimmten Schwellenwert liegen muss, bevor sich der Preis ändert.
ACTIVE_QUANTITY_DECREASEDie Menge des Abonnement-Artikels hat sich verringert, der MRR ist hiervon jedoch nicht betroffen. Dies kann passieren, wenn Sie eine gestaffelte Preisgestaltung verwenden und die Menge unter einen bestimmten Schwellenwert fallen muss, bevor sich der Preis ändert.

Notiz

Einige Nutzeraktionen können mehrere Ereignisse erstellen, sodass Sie ein Ereignis mit einem event_type von ACTIVE_END für einen Posten und dann sofort ein Ereignis mit einem event_type von ACTIVE_START für einen anderen Posten für dieselbe subscription_id sehen können.

Andere Spalten

Andere Spalten (product_id, price_id, customer_id, subscription_id und subscription_item_id) enthalten IDs im Zusammenhang mit dem Ereignis für die Änderung von Abonnementposten.

Beispielabfragen

Weitere und aktuelle Beispiele finden Sie im Abschnitt „Abonnements“ der Abfragevorlagenbibliothek in der Sigma-Seitenleiste.

Um den monatlich wiederkehrenden Umsatz (MRR) und die Anzahl der aktiven Abonnenten/Abonenntinnen anhand dieser Tabelle zu berechnen, müssen Sie Fensterfunktionen verwenden. Wenn Sie Kundinnen/Kunden haben, die verschiedene Währungen verwenden, müssen Sie außerdem Wechselkursberechnungen durchführen. Die Berechnung hat zum Ziel, den monatlichen MRR und die Entwicklung der aktiven Abonnenten/Abonnentinnen zu verfolgen und unterscheidet dabei zwischen Neuzugängen, Reaktivierungen, Erweiterungen, Minderungen und Abwanderung. Die endgültigen Ergebnisse werden in untergeordneten Währungseinheiten wie Cent (bei USD) dargestellt.

WITH ts_grouped_sub_item_events AS ( SELECT local_event_timestamp, customer_id, currency, sum(mrr_change) AS mrr_change FROM subscription_item_change_events GROUP BY 1, 2, 3 ), ts_grouped_sub_item_events_with_mrr AS ( SELECT *, date_trunc( 'day', date(local_event_timestamp) ) AS local_event_date, -- Stripe defines an "active subscriber" as a customer with non-zero MRR. -- Therefore instead of summing up event_type to get subscription count (and its diff), -- We count the amount of revenue on each customer instead and later check its movement from / to zero sum(mrr_change) over ( PARTITION by customer_id ORDER BY local_event_timestamp ASC ) AS mrr, -- We count the # of times MRR has actually changed, and use nullif to ignore events that do not impact MRR -- Otherwise we may confuse between new vs. reactivation count(nullif(mrr_change, 0)) over ( PARTITION by customer_id ORDER BY local_event_timestamp ASC ) AS mrr_change_count FROM ts_grouped_sub_item_events ), ts_grouped_sub_item_events_with_previous_mrr AS ( SELECT *, coalesce( last_value(mrr) IGNORE nulls OVER ( PARTITION by customer_id ORDER BY local_event_timestamp ASC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING ), 0 ) AS previous_mrr FROM ts_grouped_sub_item_events_with_mrr ), customer_events AS ( SELECT *, CASE WHEN mrr = 0 AND previous_mrr > 0 THEN 'ACTIVE_END' WHEN mrr > 0 AND previous_mrr = 0 AND mrr_change_count = 1 THEN 'ACTIVE_START' WHEN mrr > 0 AND previous_mrr = 0 AND mrr_change_count > 1 THEN 'REACTIVATE' WHEN mrr > previous_mrr THEN 'ACTIVE_UPGRADE' WHEN mrr < previous_mrr THEN 'ACTIVE_DOWNGRADE' ELSE NULL END AS cus_event_type FROM ts_grouped_sub_item_events_with_previous_mrr ), date_grouped_customer_events AS ( SELECT local_event_date, currency, sum(mrr_change) AS mrr_change, sum( CASE cus_event_type WHEN 'ACTIVE_START' THEN mrr_change ELSE 0 END ) AS new_mrr, sum( CASE cus_event_type WHEN 'REACTIVATE' THEN mrr_change ELSE 0 END ) AS reactivation_mrr, sum( CASE cus_event_type WHEN 'ACTIVE_UPGRADE' THEN mrr_change ELSE 0 END ) AS expansion_mrr, sum( CASE cus_event_type WHEN 'ACTIVE_DOWNGRADE' THEN mrr_change ELSE 0 END ) AS contraction_mrr, sum( CASE cus_event_type WHEN 'ACTIVE_END' THEN mrr_change ELSE 0 END ) AS churn_mrr, sum( CASE WHEN mrr = 0 AND previous_mrr > 0 THEN -1 WHEN mrr > 0 AND previous_mrr = 0 THEN 1 ELSE 0 END ) AS active_subscribers_change, sum( CASE cus_event_type WHEN 'ACTIVE_END' THEN 1 ELSE 0 END ) AS churned_subscribers, sum( CASE cus_event_type WHEN 'ACTIVE_START' THEN 1 ELSE 0 END ) AS new_subscribers, sum( CASE cus_event_type WHEN 'REACTIVATE' THEN 1 ELSE 0 END ) AS reactivated_subscribers FROM customer_events GROUP BY 1, 2 ), -- Prepare the multi dimensional table with all days + currency combinations and conversion rate metadata -- note that exchange_rates_from_usd contains one row for every date from 2010-01-07 until today -- which is why we don't need to generate a separate date series for the full table dates_with_rate_per_usd AS ( SELECT -- We use previous day's closing rates in precomputed metrics date - INTERVAL '1' DAY AS fx_date, cast( json_parse(buy_currency_exchange_rates) AS map(varchar, double) ) AS rate_per_usd FROM exchange_rates_from_usd ), currencies AS ( SELECT DISTINCT(currency) FROM subscription_item_change_events ), first_default_currency AS ( SELECT default_currency FROM accounts WHERE default_currency IS NOT NULL LIMIT 1 ), dates_x_currencies_with_conversion_rate AS ( SELECT fx_date as local_date, currency, default_currency, 1 / rate_per_usd [currency] * rate_per_usd [coalesce(default_currency, 'usd')] AS conversion_rate FROM dates_with_rate_per_usd CROSS JOIN currencies CROSS JOIN first_default_currency ORDER BY 1, 2 ), daily_metrics_by_currency AS ( SELECT dpc.local_date, dpc.currency, dpc.conversion_rate, coalesce( sum(mrr_change) over ( PARTITION by dpc.currency ORDER BY dpc.local_date ASC ), 0 ) AS mrr, coalesce( round( sum(mrr_change) over ( PARTITION by dpc.currency ORDER BY dpc.local_date ASC ) * dpc.conversion_rate ), 0 ) AS converted_mrr, coalesce(round(new_mrr * conversion_rate), 0) AS converted_new_mrr, coalesce(round(reactivation_mrr * conversion_rate), 0) AS converted_reactivation_mrr, coalesce(round(expansion_mrr * conversion_rate), 0) AS converted_expansion_mrr, coalesce(round(contraction_mrr * conversion_rate), 0) AS converted_contraction_mrr, coalesce(round(churn_mrr * conversion_rate), 0) AS converted_churn_mrr, coalesce(dgce.mrr_change, 0) AS mrr_change, coalesce(dgce.new_mrr, 0) AS new_mrr, coalesce(dgce.reactivation_mrr, 0) AS reactivation_mrr, coalesce(dgce.expansion_mrr, 0) AS expansion_mrr, coalesce(dgce.contraction_mrr, 0) AS contraction_mrr, coalesce(dgce.churn_mrr, 0) AS churn_mrr, coalesce( sum(active_subscribers_change) over ( PARTITION by dpc.currency ORDER BY dpc.local_date ASC ), 0 ) AS active_subscribers, coalesce(dgce.active_subscribers_change, 0) AS active_subscribers_change, coalesce(dgce.churned_subscribers, 0) AS churned_subscribers, coalesce(dgce.new_subscribers, 0) AS new_subscribers, coalesce(dgce.reactivated_subscribers, 0) AS reactivated_subscribers FROM dates_x_currencies_with_conversion_rate dpc LEFT JOIN date_grouped_customer_events dgce ON dpc.local_date = dgce.local_event_date AND dpc.currency = dgce.currency ), daily_metrics AS ( SELECT local_date, sum(converted_mrr) AS mrr, sum(converted_new_mrr) AS new_mrr, sum(converted_reactivation_mrr) AS reactivation_mrr, sum(converted_expansion_mrr) AS expansion_mrr, sum(converted_contraction_mrr) AS contraction_mrr, sum(converted_churn_mrr) AS churn_mrr, -- Customer can only have active subscription in a single currency at a time, as a result this does not result in over-counting subscriber changes -- This also matches the precomputed metrics logic in billing dashboard / CSV download sum(active_subscribers) AS active_subscribers, sum(churned_subscribers) AS churned_subscribers, sum(new_subscribers) AS new_subscribers, sum(reactivated_subscribers) AS reactivated_subscribers FROM daily_metrics_by_currency GROUP BY 1 ), daily_metrics_with_derived AS ( SELECT *, mrr - lag(mrr) over ( ORDER BY local_date ) - new_mrr - reactivation_mrr - expansion_mrr - contraction_mrr - churn_mrr AS fx_adjustment_mrr, lag(mrr) over ( ORDER BY local_date ) AS previous_mrr FROM daily_metrics ), -- Turn daily into monthly metrics monthly_metrics_with_derived AS ( SELECT date_trunc('month', local_date) AS local_month_start, max_by(mrr, local_date) AS ending_mrr, sum(new_mrr) AS new_mrr, sum(reactivation_mrr) AS reactivation_mrr, sum(expansion_mrr) AS expansion_mrr, sum(contraction_mrr) AS contraction_mrr, sum(churn_mrr) AS churn_mrr, sum(fx_adjustment_mrr) AS fx_adjustment_mrr, max_by(active_subscribers, local_date) AS ending_subscribers, sum(churned_subscribers) AS churned_subscribers, sum(new_subscribers) AS new_subscribers, sum(reactivated_subscribers) AS reactivated_subscribers FROM daily_metrics_with_derived GROUP BY 1 ) SELECT local_month_start, ending_mrr - fx_adjustment_mrr - churn_mrr - contraction_mrr - expansion_mrr - reactivation_mrr - new_mrr AS beginning_mrr, new_mrr, reactivation_mrr, expansion_mrr, contraction_mrr, churn_mrr, fx_adjustment_mrr, ending_mrr, -- Churned subscribers is a positive number in CSV reports instead of negative for churn / contraction mrr ending_subscribers - (-1 * churned_subscribers) - reactivated_subscribers - new_subscribers AS beginning_subscribers, new_subscribers, reactivated_subscribers, churned_subscribers, ending_subscribers FROM monthly_metrics_with_derived ORDER BY 1 DESC
local_month_startbeginning_mrrnew_mrrreactivation_mrrexpansion_mrrcontraction_mrrchurn_mrrfx_adjustment_mrrending_mrrbeginning_subscribersnew_subscribersreactivated_subscriberschurned_subscribersending_subscribers
01.05.2024100072149104000040000000100216149930012
01.04.20241000651497180000-1800100072149730012
01.03.2024100066099124000-1074010006514972027
01.02.20241000660991000000-1000010006609971017
01.01.20241000381022921601998-175-3042010006609954 $027
01.12.202310003810200000010003810250005
01.11.20231000371021000000001000381024 $1005
01.10.20231000371020000001000371024 $0004 $
01.09.20231000371020000001000371024 $0004 $
01.08.20231000339020050000-1800010003710250014 $
01.07.20231000370650000-3159-410003390260015
01.06.202310003640235336900-274211000370656134 $6
01.05.20231000348982748030437-83-3159801000364027304 $6
01.04.2023100034065933000-100010003489862017
01.03.202310000271531350000001000340654 $2006
01.02.20231000060486086060880-15507010000271552034 $
01.01.20231000060483043000-3043010000604851015
01.12.20221001521342591001363600-30000-1505574-22100006048960105
01.11.2022100178232486883333621878-10600-68939701001521347161159
01.10.202210003619313633312000020600-10000-124894010017823274 $267
War diese Seite hilfreich?
JaNein
  • Benötigen Sie Hilfe? Kontaktieren Sie den Kundensupport.
  • Nehmen Sie an unserem Programm für frühzeitigen Zugriff teil.
  • Schauen Sie sich unser Änderungsprotokoll an.
  • Fragen? Sales-Team kontaktieren.
  • LLM? Lesen Sie llms.txt.
  • Unterstützt von Markdoc