Transforming cumulative sums into monthly values

Here’s a quick BigQuery SQL exercise. I often work with cumulative aggregations, but it’s not every day that I need to reverse them—converting cumulative values back into monthly figures.
Let's look at an example.
The dataset provides cumulative sales per fiscal year (July 1st - June 30th in this case). Our goal is to determine the actual sales for each month.
How do we do it?
1. Identify the fiscal year each period belongs to. We can use a UDF (as shown) or retrieve this from a date dimension table.
2. Use the LAG window function to retrieve the previous cumulative value (partitioned by our grain + fiscal year and ordered by period).
3. Subtract the previous cumulative value from the current one to derive the actual monthly sales.
• For the first month of a fiscal year, there’s no previous value, so we default to 0 in case of a NULL there.
Things to watch out for:
➡️ Gaps in the data: How do they impact the calculation? Are we okay with that?
➡️ Grain considerations: Do we need to do this per department? Per country? If so, adjust the PARTITION BY accordingly.

-- computes the start of the respective financial year
-- (July 1st -> June 30th), given a date
CREATE TEMP FUNCTION GET_FINANCIAL_YEAR_START(input_date DATE)
RETURNS DATE
AS (
DATE(IF(EXTRACT(MONTH FROM input_date) >= 7,
EXTRACT(YEAR FROM input_date),
EXTRACT(YEAR FROM input_date) - 1), 7, 1)
);
SELECT
month_start_date,
-- computes the first day of the fiscal year
GET_FINANCIAL_YEAR_START(month_start_date) AS fiscal_year_start,
cumulative_fy_sales,
-- retrieves the previous month's cumulative sales
LAG(cumulative_fy_sales,1) OVER (PARTITION BY GET_FINANCIAL_YEAR_START(month_start_date)
ORDER BY month_start_date) AS previous_cumulative_sales,
-- calculates the sales for this particular month
cumulative_fy_sales - IFNULL(LAG(cumulative_fy_sales,1) OVER (PARTITION BY GET_FINANCIAL_YEAR_START(month_start_date)
ORDER BY month_start_date),0) AS current_month_sales
FROM input_data

Enjoyed this? Here are some related articles you might find useful: