Search code examples
google-bigquery

How can I add a calendar as a column/field to a view table?


I need to add another calendar to the current view table. The table already includes a column for month and year, but some months have no transactions, so they don't show up in the table. I want to create a new calendar field to display monthly sales, regardless of whether there are any transactions. How would I do this?

Sample script:

select  T.MONTH_YEAR,
        ROUND(SUM(T.GROSS_AMOUNT),3) AS CURRENT_GROSS_AMOUNT,
        lag(ROUND(SUM(T.GROSS_AMOUNT),3)) over (partition by T.MATERIAL order by min(T.MONTH_YEAR)) as PREV_GROSS_AMOUNT
from transactions T

Here's the output:

MONTH_YEAR CURRENT_GROSS_AMOUNT PREV_GROSS_AMOUNT
Jan 2024 200
Feb 2024 200 200
Mar 2024 300 200
Apr 2024 400 300
Jul 2024 500 400
Aug 2024 600 500

The final script should be something like this:

select  T.MONTH_YEAR,
        /*add another calendar to display 2 months no display */
        ROUND(SUM(T.GROSS_AMOUNT),3) AS CURRENT_GROSS_AMOUNT,
        lag(ROUND(SUM(T.GROSS_AMOUNT),3)) over (partition by T.MATERIAL  order by min(T.MONTH_YEAR)) as PREV_GROSS_AMOUNT
from transactions T

Which would output:

MONTH_YEAR calendar date CURRENT_GROSS_AMOUNT PREV_GROSS_AMOUNT
Jan 2024 Jan 2024 200
Feb 2024 Feb 2024 200 200
Mar 2024 Mar 2024 300 200
Apr 2024 Apr 2024 400 300
May 2024 0 400
Jun 2024 0 0
Jul 2024 Jul 2024 500 0
Aug 2024 Aug 2024 600 500

Solution

  • All you need is :

    FROM
        UNNEST(GENERATE_DATE_ARRAY('2024-01-01', '2024-12-31', INTERVAL 1 MONTH)) AS month_date
    
    
    • Step 1: Create a calendar table [ you can change the date range as per your need]. This is the part which you basically need in your code the rest you can change as you wish.

    • Step 2: Aggregate transaction data by month (what you have done so far)

    • Step 3: Left Join the calendar with transaction data, this will join the data together and still show the calendar dates which are not being used for any transaction

    
    WITH calendar AS (
      SELECT
        FORMAT_DATE('%b %Y', month_date) AS month_year,
        month_date
      FROM
        UNNEST(GENERATE_DATE_ARRAY('2024-01-01', '2024-12-31', INTERVAL 1 MONTH)) AS month_date
    ),
    
    
    transaction_data AS (
      SELECT
        FORMAT_DATE('%b %Y', PARSE_DATE('%b %Y', T.month_year)) AS month_year,
        ROUND(SUM(T.gross_amount), 3) AS current_gross_amount
      FROM
        transactions T
      GROUP BY
        month_year
    )
    
    SELECT
      c.month_year,
      IFNULL(td.current_gross_amount, 0) AS current_gross_amount,
      LAG(IFNULL(td.current_gross_amount, 0)) OVER (ORDER BY c.month_date) AS prev_gross_amount
    FROM
      calendar c
    LEFT JOIN
      transaction_data td
    ON
      c.month_year = td.month_year
    ORDER BY
      c.month_date