根据收入份额将固定月度值拆分为天数和国家/地区

时间:2021-01-14 12:48:49

标签: mysql sql

DB-Fiddle:

CREATE TABLE sales (
    id int auto_increment primary key,
    country VARCHAR(255),
    sales_date DATE,
    sales_volume INT,
    fix_costs INT
);

INSERT INTO sales
(country, sales_date, sales_volume, fix_costs
)
VALUES 

("DE", "2020-12-01", "500", "0"),
("NL", "2020-12-01", "320", "0"),
("FR", "2020-12-01", "350", "0"),

("DE", "2020-12-02", "700", "0"),
("NL", "2020-12-02", "420", "0"),
("FR", "2020-12-02", "180", "0"),

("DE", "2020-12-03", "0", "0"),
("NL", "2020-12-03", "0", "0"),
("FR", "2020-12-03", "0", "0"),

("None", "2020-12-31", "0", "2000");

预期结果:

sales_date   |   country    |   sales_volume   |     fix_costs
-------------|--------------|------------------|------------------------------------------
2020-12-01   |     DE       |       500        |     37.95  (=2000/31 = 64.5 * 0.59)
2020-12-01   |     FR       |       350        |     26.57  (=2000/31 = 64.5 * 0.41)
2020-12-01   |     NL       |       320        |      0.00
-------------|--------------|------------------|------------------------------------------
2020-12-02   |     DE       |       700        |     51.32  (=2000/31 = 64.5 * 0.8)   
2020-12-02   |     FR       |       180        |     13.20  (=2000/31 = 64.5 * 0.2)  
2020-12-02   |     NL       |       420        |      0.00
-------------|--------------|------------------|------------------------------------------    
2020-12-03   |     DE       |         0        |     32.26  (=2000/31 = 64.5 * 0.5) 
2020-12-03   |     FR       |         0        |     32.26  (=2000/31 = 64.5 * 0.5)    
2020-12-03   |     NL       |         0        |      0.00
-------------|--------------|------------------|-------------------------------------------

在上面的结果中,我想将每月 fix_cost(in this case 2000) 值拆分到国家 DEFR 每天 每日 sales_volume 在所选countries每个中。到目前为止,我已经使用了这个 question 的解决方案,效果很好:

SELECT
    sales_date, 
    country, 
    SUM(sales_volume),
    (CASE WHEN country <> 'NL'
        THEN SUM(SUM(fix_costs)) over(partition BY year(sales_date), month(sales_date))
            / day(last_day(sales_date)) 
            * SUM(sales_volume)
            / SUM(CASE WHEN country <> 'NL' THEN SUM(sales_volume) ELSE 0 END) over(partition BY sales_date)
    END) AS fix_cost_per_day
FROM sales
GROUP BY 1,2;

但是,正如您在 2020-12-03 的数据中所见,根本没有销售。
因此,上面的查询无法将当天的每日 fix_costs 拆分到每个国家/地区。
为了解决这个问题,我想修改查询,以便在一天没有 sales_volume 的情况下,值应该被分割 50/50

我必须如何修改查询才能实现此目的?

1 个答案:

答案 0 :(得分:0)

如果我理解正确的话,你。想要在每月的每一天为除 'NL' 之外的所有国家/地区分配 2,000。

这是带窗函数的算术:

  • 使用 last_day() 获取当月的天数。
  • 使用窗口函数计算除 'NL' 之外的每个国家/地区的收入比例。
  • 使用条件逻辑,因此 'NL' 很特别。

作为 SELECT 查询:

select s.*,
       (case when country = 'NL' then 0
             else ((2000 / day(last_day(sales_date))) *
                   sales_volume / nullif(sum(case when country <> 'NL' then sales_volume end) over (partition by sales_date), 0)
                  )
        end) as imputed_fixed_costs
from sales s
order by id;

注意:2000 使代码更清晰,但显然您可以使用以下方法将其输入到查询中:

from sales s cross join
     (select sum(fix_costs) as fixed_costs
      from sales
      where country = 'None'
     ) f

Here 是一个 db<>fiddle。

如果您真的想更改数据,这很容易合并到 update 中,尽管问题中的示例查询是 select

处理没有销售的月份:

select s.*,
       (case when country = 'NL'
             then 0
             when sum(case when country <> 'NL' then sales_volume end) over (partition by sales_date) > 0
             then ((2000 / day(last_day(sales_date))) *
                   sales_volume / nullif(sum(case when country <> 'NL' then sales_volume end) over (partition by sales_date), 0)
                  )
             else (2000 / day(last_day(sales_date))) * 1 / sum(country <> 'NL') over (partition by sales_date)
        end) as imputed_fixed_costs
from sales s
order by id;
相关问题