简体   繁体   中英

Calculating membership revenue per day

I have a membership table with the colums ID, Start_date, End_date, Duration, Value

ID | Start_date | End_date | Duration | Value |
1  | 2012-08-12 |2012-09-12|    30    |   10  |
2  | 2011-05-22 |2013-05-22|   720    |  2000 |

and so on

I want to turn it into two colums, one which has the date, each day of the year, and the other which has the sum of all Value/duration of memberships on that day.

I eventually need to turn it into a per month value, giving me a clear picture of what revenues to expect in the future thanks to running memberships.

Right now I did something like

select 
sum(if("2012-01-01" between start_date and end_date, total_value/duration, null)) as "2012-01-01",
sum(if("2012-01-02" between start_date and end_date, total_value/duration, null)) as "2012-01-02",
[...]
sum(if("2013-12-31" between start_date and end_date, total_value/duration, null)) as "2013-12-31"

from MembershipsTable

/* 0 rows affected, 1 rows found. Duration for 1 query: 3,666 sec. */

but I do not see how I could easily sum them up to give me a per-month value. I could just create a sum of the columns again, but would rather not have to type in novels of text

Run time is not an issue for the current format

I need an output of the shape

Month    | Sum    |
Jan 2012 |4500    |
Feb 2012 |4215,91 |

Where the sum is the sum of all memberships intersecting that period calculated by price per day*number of days the membership has in the month.

So if a membership starts on 12 Nov, Ends 11 Dec, has a duration of 30, value of 300, I want to add 300/30*daysInNov to month november, same for dec, giving me +190 for Nov, +110 for Dec I need a sum of all memberships in that way.

Does anyone have any idea?

This is a bit of an ugly hack, but I believe something like the below would work if I'm understanding your needs correctly.

First, create a tabled named month_days that has all the months with their start and end date. You would use this as a utility table to join against and calculate monthly totals.

month_days
start_date | last_date 
2012-01-01 | 2012-01-31
2012-02-01 | 2012-02-29

Then, execute a join and calculation something like this:

select format(month_days.start_date, 'MMM yyyy') AS [Month],
       sum(case when (memberships.start_date > month_days.start_date AND memberships.end_date < month_days.end_date)
              then datediff(day, memberships.end_date, memberships.start_date) * (value/duration)
            when (memberships.start_date between month_days.start_date and month_days.end_date)
              then (datediff(day, month_days.end_date, memberships.start_date) + 1) * (value/duration)
            when (memberships.end_date between month_days.start_date and month_days.end_date)
              then datediff(day, memberships.end_date, month_days.start_date) * (value/duration)
            else (datediff(day, month_days.end_date, month_days.start_date) + 1) * (value/duration)
        end) total_value
from memberships
inner join month_days
on memberships.start_date < month_days.end_date
and memberships.end_date > month_days.start_date
group by month_days.start_date
order by month_days.start_date

There are many ways to create the month_days table that would achieve a similar effect.

You could probably also write a stored procedure to iterate through the months for each record, populate a temp table (or table variable) with the monthly sums, then return the contents of the temp table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM