简体   繁体   中英

BigQuery: Split monthly data into days

I want to create a new table from the existing data:

date store cost
2022-01-10 a 3000
2022-01-10 b 2500

And finally the targettable should look like:

date store cost
2022-01-10 a 96,77
2022-02-10 a 96,77
2022-03-10 a 96,77
2022-04-10 a 96,77
.... to last day of the month a 96,77
2022-01-10 b 80,65
2022-02-10 b 80,65
2022-03-10 b 80,65
... b 80,65

The query should insert into another bigquery table with new rows for each day of the month (like the 2nd table). The cost should devided by the day of the month to split the cost.

I tried a few querys, but cant find a solution: :(

Thank you!

Using this answer here I have calculated the number of days for each month, and then I have divided the monthly costs by it to get daily_avg_monthly_cost . Then I Joined with an array generated table containing all the dates in each month of the year and got the final output.

Please note: a limitation of this solution is that the value "2022" is hardcoded.

WITH source_data as (
    SELECT date('2022-01-10') as _month, 'a' as store, 3000 as cost
    UNION ALL
    SELECT date('2022-01-10') as _month, 'b' as store, 2500 as cost
    UNION ALL
    SELECT date('2022-02-10') as _month, 'a' as store, 4000 as cost
    UNION ALL
    SELECT date('2022-02-10') as _month, 'b' as store, 3500 as cost
 ), cost_table AS (
        SELECT
            FORMAT_DATE('%Y-%m', _month) AS month,
            store,
            cost/EXTRACT(DAY FROM (DATE_SUB(DATE_TRUNC(DATE_ADD(_month, INTERVAL 1 MONTH), MONTH),INTERVAL 1 DAY))) daily_avg_monthly_cost
        FROM source_data
),days AS (
        SELECT
            d, 
            FORMAT_DATE('%Y-%m',d) AS month
            FROM (
                SELECT 
                    *
                FROM
                UNNEST(GENERATE_DATE_ARRAY('2022-01-01', '2022-12-31', INTERVAL 1 DAY)) AS d 
            )
)
    SELECT
        days.d as date,
        cost_table.store,
        cost_table.daily_avg_monthly_cost
    FROM cost_table
    JOIN days ON CAST(cost_table.month AS STRING) = days.month

You might consider below as well.

WITH sample_table AS (
  SELECT '2022-01-10' date, 'a' store, 3000 cost UNION ALL
  SELECT '2022-01-10' date, 'b' store, 2500 cost
)
SELECT store, date, ROUND(cost / COUNT(1) OVER (PARTITION BY store, _date), 2) cost 
  FROM (
    SELECT store, cost,
           -- parse *date* STRING to DATE type
           PARSE_DATE('%Y-%d-%m', date) AS _date,
      FROM sample_table
  ), UNNEST(GENERATE_DATE_ARRAY(DATE_TRUNC(_date, MONTH), LAST_DAY(_date))) date;
  • LAST_DAY : Returns the last day from a date expression. This is commonly used to return the last day of the month.

Query results

在此处输入图像描述

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