SQL 服务器价格 table 加权购买价格
SQL Server price table weighted to buying price
我有 3 个 table:
买入
ID
Item
qty
price
1
1001
10
1.00
2
1001
10
2.00
3
1001
10
3.00
4
1002
10
2.00
5
1002
10
1.00
6
1003
10
1.00
7
1004
10
1.00
8
1004
10
2.00
回退
Item
price
1001
3.00
1002
3.00
1003
4.00
股票
Item
stock
1001
15
1002
5
1003
25
1004
15
我必须计算每件商品的实际价格。为此,我必须从最大 ID 到最小 ID 检查每行 table“购买”,并在库存充足的情况下获取所有价格。如果在table买的不够多,我就得用部分股票的后备价格,我先没有价格在table.
因此对于项目编号。 1001,库存为 15。在 ID 3 中找到 10 件的价格(3.00 美元);行 ID 2 中剩余 5 件的价格(2.00 美元)。所以正确的实际股价是 2.66 美元。
商品编号1002,库存为 5。行 ID 5 中的最新购买价格为 1.00 美元,数量超过 5。因此正确的实际库存价格为 1.00 美元。
商品编号1003,库存为 25。ID 6 行中只有一个条目,10 个,每个 1.00 美元。所以缺少 15 件的价格必须从后备 table 4.00 美元中扣除。所以正确的实际股价是 2.80 美元。
结果应该是这样的:
Item
stock
value
1001
15
2.66
1002
5
1.00
1003
25
2.80
但我不知道它是如何工作的。非常感谢您的帮助。
您需要创建 Buys
中数量的 运行 总和,并以此为基础计算价格。
这有点复杂,因为 Buys
中的行数可能太多或不够,无法完成库存。
SELECT
s.Item,
s.stock,
(
ISNULL(b.FoundStockPrice, 0)
+ CASE WHEN s.stock > ISNULL(b.FoundStock, 0)
THEN s.stock - ISNULL(b.FoundStock, 0)
ELSE 0 END * f.price
) / s.stock
FROM Stock s
JOIN Fallback f ON f.Item = s.Item
OUTER APPLY (
SELECT
FoundStock = SUM(b.qty),
FoundStockPrice = SUM(
CASE WHEN b.FullStock > b.RunningSum THEN b.qty
ELSE b.FullStock - (b.RunningSum - b.qty) END
* b.price)
FROM (
SELECT *,
RunningSum = SUM(b.qty) OVER (PARTITION BY b.Item
ORDER BY b.ID DESC ROWS UNBOUNDED PRECEDING),
FullStock = s.stock
FROM Buys b
WHERE b.Item = s.Item
) b
WHERE b.RunningSum - b.qty < s.stock
) b;
步骤如下:
- 对于每个
Stock
取所有相关的 Buys
行。
- 计算
qty
的 运行 总和,然后过滤到 运行 总和 包含 最终 [=16] 的行=](换句话说它必须达到之前的运行和)。
- 将这些
Buys
行乘以它们的 price
,考虑到我们需要扣除任何超过必要的 stock
。也取数量的总和。
- 最终价格是:之前计算的总价,加上任何剩余未找到的
stock
乘以fallback.price
,再除以总价stock
。
比较股票时使用条件聚合来购买运行总计,最后应用后备
select t.item, (s + t.qf * f.price) s, stock, (s + t.qf * f.price) / stock price
from (
select s.Item, s.Stock,
sum(coalesce(case when b.qe <= Stock then b.qty else Stock - b.qs end * b.price, 0)) s,
-- qty for fallback
min(case when Stock > coalesce(b.qe,0) then Stock - coalesce(b.qe,0) else 0 end) qf
from Stock s
left join (
select Item, qty, price, ID,
sum(qty) over(partition by Item order by ID desc) - qty qs, -- starting runnig total
sum(qty) over(partition by Item order by ID desc) qe -- ending runnig total
from Buys
) b on s.Item = b.Item and s.Stock > b.qs
group by s.Item, s.Stock
) t
join Fallback f on f.Item = t.Item;
order by t.Item;
如果某个项目可能缺少后备,则需要进行细微调整。
select t.item, (s + t.qf * coalesce(f.price, 0)) s, stock, (s + t.qf * coalesce(f.price, 0)) / stock price
from (
select s.Item, s.Stock,
sum(coalesce(case when b.qe <= Stock then b.qty else Stock - b.qs end * b.price, 0)) s,
-- qty for fallback
min(case when Stock > coalesce(b.qe,0) then Stock - coalesce(b.qe,0) else 0 end) qf
from Stock s
left join (
select Item, qty, price, ID,
sum(qty) over(partition by Item order by ID desc) - qty qs, -- starting runnig total
sum(qty) over(partition by Item order by ID desc) qe -- ending runnig total
from Buys
) b on s.Item = b.Item and s.Stock > b.qs
group by s.Item, s.Stock
) t
left join Fallback f on f.Item = t.Item
where t.qf = 0 or f.item is not null
order by t.Item;
如果需要回退但缺少回退,则查询将不会 return 一行。否则该行是 returned.
我有 3 个 table:
买入
ID | Item | qty | price |
---|---|---|---|
1 | 1001 | 10 | 1.00 |
2 | 1001 | 10 | 2.00 |
3 | 1001 | 10 | 3.00 |
4 | 1002 | 10 | 2.00 |
5 | 1002 | 10 | 1.00 |
6 | 1003 | 10 | 1.00 |
7 | 1004 | 10 | 1.00 |
8 | 1004 | 10 | 2.00 |
回退
Item | price |
---|---|
1001 | 3.00 |
1002 | 3.00 |
1003 | 4.00 |
股票
Item | stock |
---|---|
1001 | 15 |
1002 | 5 |
1003 | 25 |
1004 | 15 |
我必须计算每件商品的实际价格。为此,我必须从最大 ID 到最小 ID 检查每行 table“购买”,并在库存充足的情况下获取所有价格。如果在table买的不够多,我就得用部分股票的后备价格,我先没有价格在table.
因此对于项目编号。 1001,库存为 15。在 ID 3 中找到 10 件的价格(3.00 美元);行 ID 2 中剩余 5 件的价格(2.00 美元)。所以正确的实际股价是 2.66 美元。
商品编号1002,库存为 5。行 ID 5 中的最新购买价格为 1.00 美元,数量超过 5。因此正确的实际库存价格为 1.00 美元。
商品编号1003,库存为 25。ID 6 行中只有一个条目,10 个,每个 1.00 美元。所以缺少 15 件的价格必须从后备 table 4.00 美元中扣除。所以正确的实际股价是 2.80 美元。
结果应该是这样的:
Item | stock | value |
---|---|---|
1001 | 15 | 2.66 |
1002 | 5 | 1.00 |
1003 | 25 | 2.80 |
但我不知道它是如何工作的。非常感谢您的帮助。
您需要创建 Buys
中数量的 运行 总和,并以此为基础计算价格。
这有点复杂,因为 Buys
中的行数可能太多或不够,无法完成库存。
SELECT
s.Item,
s.stock,
(
ISNULL(b.FoundStockPrice, 0)
+ CASE WHEN s.stock > ISNULL(b.FoundStock, 0)
THEN s.stock - ISNULL(b.FoundStock, 0)
ELSE 0 END * f.price
) / s.stock
FROM Stock s
JOIN Fallback f ON f.Item = s.Item
OUTER APPLY (
SELECT
FoundStock = SUM(b.qty),
FoundStockPrice = SUM(
CASE WHEN b.FullStock > b.RunningSum THEN b.qty
ELSE b.FullStock - (b.RunningSum - b.qty) END
* b.price)
FROM (
SELECT *,
RunningSum = SUM(b.qty) OVER (PARTITION BY b.Item
ORDER BY b.ID DESC ROWS UNBOUNDED PRECEDING),
FullStock = s.stock
FROM Buys b
WHERE b.Item = s.Item
) b
WHERE b.RunningSum - b.qty < s.stock
) b;
步骤如下:
- 对于每个
Stock
取所有相关的Buys
行。 - 计算
qty
的 运行 总和,然后过滤到 运行 总和 包含 最终 [=16] 的行=](换句话说它必须达到之前的运行和)。 - 将这些
Buys
行乘以它们的price
,考虑到我们需要扣除任何超过必要的stock
。也取数量的总和。 - 最终价格是:之前计算的总价,加上任何剩余未找到的
stock
乘以fallback.price
,再除以总价stock
。
比较股票时使用条件聚合来购买运行总计,最后应用后备
select t.item, (s + t.qf * f.price) s, stock, (s + t.qf * f.price) / stock price
from (
select s.Item, s.Stock,
sum(coalesce(case when b.qe <= Stock then b.qty else Stock - b.qs end * b.price, 0)) s,
-- qty for fallback
min(case when Stock > coalesce(b.qe,0) then Stock - coalesce(b.qe,0) else 0 end) qf
from Stock s
left join (
select Item, qty, price, ID,
sum(qty) over(partition by Item order by ID desc) - qty qs, -- starting runnig total
sum(qty) over(partition by Item order by ID desc) qe -- ending runnig total
from Buys
) b on s.Item = b.Item and s.Stock > b.qs
group by s.Item, s.Stock
) t
join Fallback f on f.Item = t.Item;
order by t.Item;
如果某个项目可能缺少后备,则需要进行细微调整。
select t.item, (s + t.qf * coalesce(f.price, 0)) s, stock, (s + t.qf * coalesce(f.price, 0)) / stock price
from (
select s.Item, s.Stock,
sum(coalesce(case when b.qe <= Stock then b.qty else Stock - b.qs end * b.price, 0)) s,
-- qty for fallback
min(case when Stock > coalesce(b.qe,0) then Stock - coalesce(b.qe,0) else 0 end) qf
from Stock s
left join (
select Item, qty, price, ID,
sum(qty) over(partition by Item order by ID desc) - qty qs, -- starting runnig total
sum(qty) over(partition by Item order by ID desc) qe -- ending runnig total
from Buys
) b on s.Item = b.Item and s.Stock > b.qs
group by s.Item, s.Stock
) t
left join Fallback f on f.Item = t.Item
where t.qf = 0 or f.item is not null
order by t.Item;
如果需要回退但缺少回退,则查询将不会 return 一行。否则该行是 returned.