我正在为一个葡萄酒进口商开展一个项目,该项目需要计算到交货日期为止每个SKU的累计仓储费。
我从仓库中记录了Date_In
和Date_Out
的数据,因此计算DATEDIFF('day', Date_In, Date_Out)
相当简单。
但是,每年仓库都会改变价格,因此在计算仓储费用时,我需要将Days_in_Stock
分配给不同的费率。
输入具有库存变动日期的数据:
+----------------+------------+---------+-----+------------+------------+
| INVOICE_NUMBER | STOCK_CODE | CS_SIZE | QTY | DATE_IN | DATE_OUT |
+----------------+------------+---------+-----+------------+------------+
| 1001 | MP-BMB13 | 6 | 1 | 2019-03-01 | 2019-06-01 |
| 1002 | MP-BMB13 | 6 | 1 | 2019-03-01 | 2019-10-01 |
+----------------+------------+---------+-----+------------+------------+
存储率:
+----------------+-----------+-------------+
| DATE_EFFECTIVE | CASE_SIZE | COST_PER_WK |
+----------------+-----------+-------------+
| 2018-09-01 | 9 | 0.1375 |
| 2018-09-01 | 6 | 0.06875 |
| 2019-09-01 | 9 | 0.1425 |
| 2010-09-01 | 6 | 0.07125 |
+----------------+-----------+-------------+
我想要的输出如下:
+----------------+------------+---------------+--------------+
| INVOICE_NUMBER | STOCK_CODE | DAYS_IN_STOCK | STORAGE_COST |
+----------------+------------+---------------+--------------+
| 1001 | MP-BMB13 | 92 | 0.90 |
| 1002 | MP-BMB13 | 214 | 2.10 |
+----------------+------------+---------------+--------------+
DAYS_IN_STOCK
用DATEDIFF('day', Date_In, Date_Out)
STORAGE_COST
是COST_PER_WK * DAYS_IN_STOCK / 7
我遇到的问题是DAYS_IN_STOCK
与Invoice 1002一样跨越多个收费率。在这种情况下,计算需要像这样:
COST_PER_WK (before 2019-09-01)* DAYS_IN_STOCK (before 2019-09-01) / 7
+
COST_PER_WK (since 2019-09-01)* DAYS_IN_STOCK (since 2019-09-01) / 7
理想情况下,最终查询将能够处理该商品在两个以上的收费时段内的库存情况。
到目前为止尝试的方法:
Date_In
联接到Date_Effective
,但我无法使其正常工作,也不知道如何扩展到3个价格。我对如何解决这个问题感到很困惑,因此任何想法都将受到欢迎。 当前正在使用SQL Server 2017
答案 0 :(得分:0)
这应该为您提供解决方法的思路。我不想处理数周,因此我将用几天来表达这个答案。
基本思想是将结束日期添加到费率表,然后使用join
和汇总:
with sr as (
select r.*,
lead(date_effective) over (partition by case_size) as date_end,
cost_per_wk / 7.0 as cost_per_day
from storage_rates r
)
select i.*, sr.total_cost
from invoices i outer apply
(select sum(datediff(day,
(case when i.date_in > sr.date_effective then i.date_in else sr.date_effective end),
(case when i.date_out < sr.date_eend then i.date_out else sr.date_end end)
) * sr.cost_per_day
) as total_cost
from sr
where i.cs_size = sr.cs_size and -- I think the case size is relevant
i.date_in < sr.date_end and
i.date_out >= sr.date_effective
) sr;