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)
值拆分到国家 DE
和 FR
每天 每日 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。
我必须如何修改查询才能实现此目的?
答案 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;