Я пытаюсь рассчитать средневзвешенную цену акций, используя Microsoft SQL Server 2016.
Разница в том, что я спрашиваю, состоит в том, что, когда все акции были проданы, взвешенная цена должна быть сброшена
Выпуск
NewPrice неверен в следующей таблице сделок
![enter image description here](https://i.stack.imgur.com/xxDaq.png)
Ожидаемый результат
Row NewPrice
1 186.4000
2 186.4000
3 183.0800
4 183.0800
5 183.0800
6 183.0800
7 183.0800
8 183.0800
7 183.0800
Запрос
SELECT *,
PriceRunningTotalFinal =
SUM(CASE
WHEN QuantityRunningTotal = 0 THEN -1 * PriceRunningTotal
WHEN Units < 0 THEN 0 ELSE PurchasePrice * Units END) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
CASE WHEN Results1.QuantityRunningTotal <= 0 then 0
else
SUM(CASE
WHEN QuantityRunningTotal <= 0 THEN -1 * PriceRunningTotal
WHEN Units < 0 THEN 0 ELSE PurchasePrice * Units END) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
) / Results1.QuantityRunningTotal
end as NewPrice
FROM
(
SELECT Id, UserCompetitionId, StockId, Type, Units, PurchasePrice, CreatedOn,
QuantityRunningTotal = SUM(Units) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
PriceRunningTotal = SUM(CASE WHEN Units <= 0 THEN 0 ELSE PurchasePrice * Units END) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
)
FROM Trade
) AS Results1
WHERE UserCompetitionId =@UserCompetitionId AND StockId = 122
У меня проблема с новой ценой.
С Строка 4 и далее цена должна быть 183.08000
Это связано с тем, что все предыдущие акции были проданы (количествоRunningTotal равно 0). Поэтому расчет взвешенной цены покупки должен начаться заново, а не принимать во внимание предыдущие строки
UPDATE
Глядя на Андрей Одегов ответ, решение работает. Но я не упомянул одну вещь - я хотел бы получить скорректированные взвешенные цены для каждой строки.
Как видно на этом скриншоте:
![enter image description here](https://i.stack.imgur.com/HBTan.png)
Средневзвешенная цена
Я пытался получить среднюю цену, она вроде работает, но я не уверен, что это правильный путь?
DECLARE @Trade TABLE(
Id INT IDENTITY,
UserCompetitionId INT DEFAULT(92170),
StockId INT DEFAULT(122),
Type INT,
Units INT,
PurchasePrice NUMERIC(8, 4)
);
INSERT @Trade(Type, Units, PurchasePrice)
VALUES (10, 42, 186.4),
(20, -42, 183.08),
(10, 40, 183.08),
(20, -5, 183.92),
(20, -1, 181.68),
(20, -1, 181.68),
(20, -1, 181.68),
(20, 17, 181.68),
(20, -10, 181.68);
WITH
A AS(
SELECT
*,
QuantityRunningTotal = SUM(Units) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
)
FROM @Trade
),
B AS (
SELECT
*,
Grp = SUM(IIF(QuantityRunningTotal - Units <= 0, 1, 0)) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
)
FROM A
)
SELECT *, TotalAmount / Qty
FROM (
SELECT
*,
Units * PurchasePrice AS PurchaseAmount,
NewPrice = FIRST_VALUE(PurchasePrice) OVER
(
PARTITION BY UserCompetitionId, StockId, Grp
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
row_number() over (partition by UserCompetitionId, StockId order by Id desc) as Seq,
TotalAmount = SUM(CASE WHEN Units < 0 THEN 0 ELSe Units * PurchasePrice END) OVER
(
PARTITION BY UserCompetitionId, StockId, Grp
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
Qty = SUM(CASE WHEN Units < 0 THEN 0 ELSe Units END) OVER
(
PARTITION BY UserCompetitionId, StockId, Grp
ORDER BY Id ROWS UNBOUNDED PRECEDING
)
FROM B
)AS Result
WHERE Result.Seq = 1 AND QuantityRunningTotal > 0
ORDER BY StockId;
UPDATE2 (Получает общую стоимость покупки $ 50,65)
DECLARE @Trade TABLE(
Id INT IDENTITY,
UserCompetitionId INT DEFAULT(92170),
StockId INT DEFAULT(122),
Units INT,
PurchasePrice NUMERIC(8, 4)
);
INSERT @Trade(Units, PurchasePrice)
VALUES (100, 97.8774),
(200, 97.89),
(-300, 97.8858),
(600, 48.9429),
(100, 60.9),
(-600, 60.395);
WITH
A AS(
SELECT
*,
Amount = SUM(IIF(Units > 0, Units * PurchasePrice, 0)) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
Qty = SUM(IIF(Units > 0, Units, 0)) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
Qty2 = SUM(Units) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
),
TotalAmount = SUM(Units * PurchasePrice) OVER
(
PARTITION BY UserCompetitionId, StockId
ORDER BY Id ROWS UNBOUNDED PRECEDING
)
FROM @Trade
)
SELECT
Units AS Amount,
CAST(PurchasePrice AS NUMERIC(6,2)) AS [Purchase Price],
CAST(ABS(Units * PurchasePrice) AS NUMERIC(12,2)) AS [Purchase Amount],
CAST(Amount / Qty AS NUMERIC(6, 2)) AS "Adjusted Purchase Price",
Qty2,
TotalAmount,
IIF(Qty2 = 0, 0,TotalAmount/ Qty2) AS Average
FROM A
ORDER BY Id;
Любые идеи будут с благодарностью.