1

Der Hintergrund dafür ist, dass ich MRR (Monthly Recurring Revenue) für ein Abonnement-basiertes Geschäft berechnen möchte, wo der Umsatz erfasst wird, wenn ein Verkauf getätigt wird, zusammen mit dem Zeitraum des Vertrags, repräsentiert durch den effektiven Endtermin.Wie verteilt man den Umsatz über einen variablen Zeitraum (monatlich, jährlich usw.) mit SQL?

Die Aufgabe ist dann, den Umsatz in die Laufzeit des Vertrags zu teilen und mehrere Verträge zu aggregieren, so dass der Umsatz pro Monat angezeigt werden kann. Es wäre ein Vorteil, auch die Abwanderung zu zeigen, d. H. Den $ Verlust, der auftritt, wenn ein Vertrag zu einem Ende kommt und nicht erneuert wird.

Das Format der Daten als solche (die Abrechnungsperiode ignorieren):

╔══════════════════════════════════╦══════════════════════════╦══════════════════════════╦════════════════╦═══════╗ 
║   account_id   ║  start_date  ║ effective_end_date ║ billing_period ║ price ║ 
╠══════════════════════════════════╬══════════════════════════╬══════════════════════════╬════════════════╬═══════╣ 
║ 2c92a0fd5286d62801528d6578230fa7 ║ 2015-10-01T00:00:00.000Z ║ 2017-10-15T00:00:00.000Z ║ Annual   ║ 1440 ║ 
║ 2c92a0fd5286d62801528d6578230fa8 ║ 2015-10-01T00:00:00.000Z ║ 2016-10-15T00:00:00.000Z ║ Annual   ║ 3500 ║ 
║ 2c92a0fd5286d62801528d6578230fa9 ║ 2015-10-01T00:00:00.000Z ║ 2015-12-31T00:00:00.000Z ║ Annual   ║ 700 ║ 
╚══════════════════════════════════╩══════════════════════════╩══════════════════════════╩════════════════╩═══════╝ 

Das gewünschte Ergebnis der folgenden würde zeigen:

2c92a0fd5286d62801528d6578230fa7 $ 1.440 über 24 Monate verteilt, ab Oktober 2015 bis Oktober verbreitet 2017.

2c92a0fd5286d62801528d6578230fa8 $ 3500 mehr als 12 Monate, von Oktober 2015 bis Oktober 2016.

2c92a0fd5286d62801528d6578230fa9 breitet $ 700 mehr als 3 Monate, von Oktober 2015 bis 2015 Dezember

Ich weiß, dass ich ein Datum Tabelle verwenden muß, um zu überqueren zu kommen, weil sonst alle Daten nicht dargestellt werden würden. Ich kann das mit einem CTE tun. Aber ich bin mehr verwirrt, wie man die Einnahmen teilt. Jede Hilfe wäre willkommen! Diese

ist, wo ich schon so weit gekommen zu:

SELECT account_id, date_trunc('month',effective_start_date) as start_date, effective_end_date, mrr as price, 
EXTRACT(YEAR FROM age(date_trunc('month',effective_end_date)::date,date_trunc('month', effective_start_date)::date))*12 + EXTRACT(month from age(date_trunc('month',effective_end_date)::date,date_trunc('month', effective_start_date)::date)) as contract_length_months, 
mrr/NULLIF(EXTRACT(YEAR FROM age(date_trunc('month',effective_end_date)::date,date_trunc('month', effective_start_date)::date))*12 + EXTRACT(month from age(date_trunc('month',effective_end_date)::date,date_trunc('month', effective_start_date)::date)),0) as divided_price 
FROM "public"."zuora_rate_plan_charge" where mrr <> 0 and mrr is not null 
order by date_trunc('month',effective_start_date) 

Ergebnis:

╔══════════════════════════════════╦══════════════════════════╦══════════════════════════╦═══════╦════════════════════════╦═══════════════╗ 
║   account_id   ║  start_date  ║ effective_end_date ║ price ║ contract_length_months ║ divided_price ║ 
╠══════════════════════════════════╬══════════════════════════╬══════════════════════════╬═══════╬════════════════════════╬═══════════════╣ 
║ 2c92a0fd5286d62801528d6578230fa7 ║ 2015-10-01T00:00:00.000Z ║ 2017-10-15T00:00:00.000Z ║ 1440 ║      24 ║   60 ║ 
╚══════════════════════════════════╩══════════════════════════╩══════════════════════════╩═══════╩════════════════════════╩═══════════════╝ 

Gewünschtes Ergebnis:

╔════════╦════════════════╗ 
║ Month ║  MRR  ║ 
╠════════╬════════════════╣ 
║ Oct 15 ║ 585   ║ 
║ Nov 15 ║ 585   ║ 
║ Dec 15 ║ 585   ║ 
║ Jan 16 ║ 351.6666666667 ║ 
╚════════╩════════════════╝ 

Antwort

0

Sie können generate_series() verwenden, um die Monate und dann einige Arithmetik zu erhalten, um die Daten zu erhalten.Um alle Monate für einen Kunden:

select t.*, price/count(*) over (partition by account_id) as monthy 
from (select t.*, 
      generate_series(start_date, end_date, interval '1 month') as yyyymm 
     from t 
    ) t; 

Dann können Sie diese aggregieren, wenn Sie den Betrag pro Monat wollen:

select yyyymm, sum(monthly) 
from (select t.*, 
      price/count(*) over (partition by account_id) as monthly 
     from (select t.*, 
        generate_series(start_date, end_date, interval '1 month') as yyyymm 
      from t 
      ) t 
    ) t 
group by yyyymm 
order by yyyymm; 
0

Hier einige Tipps, ist das könnte hilfreich. Die Idee ist einfach, Sie können einfach eine Dummy-Tabelle erstellen, die nur YEAR-MONTH enthält und sich ihr anschließen, um die gewünschten Daten zu erhalten.

  1. In solchen Fällen habe ich Dummy-Tabelle zu machen, kommen die nur über Jahr-Monat Spalte ex) 2012-02, 2012-03, 2012-04, ~~~ 2020-12
  2. Hier ist einfache Abfrage, um den Preis in jedem Monat zu erhalten. ex) SELECT Preis/TIMESTAMPDIFF (Monat, start_date, end_date) AS Gehalt, start_date, end_date VON TESTTABLE
  3. Join the (1) Tisch und Ihr Ergebnis und das Gehalt von der Gruppe erhalten, indem (1) Spalten ..

Viel Glück.

Verwandte Themen