简体   繁体   中英

Adjust column value based on difference between 2 dates

I have sales data at the start of every month in a quarter.

Example: For 22-Q1 quarter, I have sales on 3 dates (1st Jan, 1st Feb and 1st March)

Date Country Region Sales
01/01/2022 UK EMEA 100,000
02/01/2022 UK EMEA 170,000
03/01/2022 UK EMEA 120,000
01/01/2022 US AMS 90,000
02/01/2022 US AMS 110,000
03/01/2022 US AMS 160,000

My requirement is to extrapolate the Sales data between the 2 given dates based on difference between the 2 dates and concatenate them to the same table.

For example for 2nd Jan, I calculate the date difference between 1st Jan and 1st Feb, which is 31 days and increment Sales amount by (1/31) and for 3rd Jan, I increment Sales amount by (2/31).. so on until 31st Jan.

After the month change, the date difference needs to be recalculated between 1st Feb and 1st March and similar increment on Sales needs to be applied

You can use a UDTF to generate the rows for each day of the month along with an extrapolation of the sales.

create or replace table T1 as 
select 
COLUMN1::date   as Date,
COLUMN2::string as Country,
COLUMN3::string as Region,
COLUMN4::number(38,2) as Sales
from (values
('01/01/2022','UK','EMEA',100000),
('02/01/2022','UK','EMEA',170000),
('03/01/2022','UK','EMEA',120000),
('01/01/2022','US','AMS',90000),
('02/01/2022','US','AMS',110000),
('03/01/2022','US','AMS',160000)
);

create or replace function EXTRAPOLATE_MONTH_TO_DAYS(MONTH_START date, VAL float)
returns table (DAY_DATE date, VAL float)
language javascript
as
$$
{
    initialize: function (argumentInfo, context) {
    },
    processRow: function (row, rowWriter, context) {
        const DAY = 86400000; // Milliseconds per day.
        let firstDay = row.MONTH_START;
        let lastDay = new Date(row.MONTH_START.getFullYear(), row.MONTH_START.getMonth() + 1, 0);
        let daysInMonth = lastDay.getDate();
        let valPerDay = row.VAL / daysInMonth;
        let sum = 0;
        let curDate = row.MONTH_START;
        for (let i = 1; i <= daysInMonth; i++) {
            sum += valPerDay;
            rowWriter.writeRow({DAY_DATE:new Date(firstDay.getTime()+DAY*(i-1)),VAL:sum});
        }
    },
}
$$;


select   DATE
        ,COUNTRY
        ,REGION
        ,SALES
        ,DAY_DATE
        ,round(VAL,2)::number(38,2) EXTRAPOLATED_RUNNING_TOTAL
from T1, table(EXTRAPOLATE_MONTH_TO_DAYS(DATE, SALES::float) over (partition by COUNTRY, REGION order by DATE))
;

First five rows:

DATE COUNTRY REGION SALES DAY_DATE EXTRAPOLATED_RUNNING_TOTAL
2022-01-01 US AMS 90000 2022-01-01 2903.23
2022-01-01 US AMS 90000 2022-01-02 5806.45
2022-01-01 US AMS 90000 2022-01-03 8709.68
2022-01-01 US AMS 90000 2022-01-04 11612.90
2022-01-01 US AMS 90000 2022-01-05 14516.13

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