У меня есть таблица, которая выглядит так:
Мне нужно взять Available_SOH из самого раннего DocNum и вычесть его из Required_SOH, а затем обновить Available_SOH, указав остаток в следующем DocNum. Это будет справедливо для каждой комбинации источника, местоположения, ячейки и позиции.
Таким образом, используя приведенный выше пример данных для комбинации Source, Loc, Bin, Item (A, ZA, 3, ABC), самый ранний DocNum равен 3 и, следовательно, ему присвоено значение Available_SOH. Обратите внимание, что всем самым ранним номерам документов в таблице для соответствующей комбинации присвоено значение SOH, которое в данном случае указывает на доступный запас для этого конкретного товара (ABC).
Мне нужно взять баланс 7440 (Avail_SOH 25000 - Req_SOH 17560) и назначить его Availabe_SOH для DocNum 5, потому что это следующий DocNum для этой комбинации. Затем следуйте той же логике, что и Avail_SOH 7440 — Req_SOH 5810 = 1630, которая перейдет в Available_SOH для DocNum 6.
Поэтому результат будет выглядеть так:
Короче говоря, мне нужно перенести остаток запаса на следующий DocNum для комбинации Source, Loc, Bin, Item. По сути, номера DocNums, которые были созданы первыми, получают выполнение запасов.
Мне очень сложно сформулировать, что мне нужно, но я надеюсь, что это имеет смысл.
Это то, что я пробовал, но это не дает желаемого результата
WITH OrderedData AS (
SELECT
DocNum,
Source,
Loc,
Bin,
Item,
Required_SOH,
COALESCE(Available_SOH, 0) AS SOH,
ROW_NUMBER() OVER (PARTITION BY Source, Loc, Bin, Item ORDER BY DocNum) AS RowNum
FROM #TempSOH
),
CalculatedSOH AS (
SELECT
DocNum,
Source,
Loc,
Bin,
Item,
Required_SOH,
Available_SOH,
SUM(Available_SOH) OVER (PARTITION BY Source, Loc, Bin, Item ORDER BY RowNum ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) - Required_SOH AS SOH_Calculated
FROM OrderedData
)
SELECT
DocNum,
Source,
Loc,
Bin,
Item,
Required_SOH,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY Source, Loc, Bin, Item ORDER BY DocNum) = 1 THEN SOH_Calculated
ELSE LAG(SOH_Calculated, 1, 0) OVER (PARTITION BY Source, Loc, Bin, Item ORDER BY DocNum)
END AS SOH
FROM CalculatedSOH
ORDER BY DocNum;
Я не проверял это, но думаю, что это сделает то, что вы просите.
Я думаю, что вместо использования оконных функций лучший способ получить промежуточную сумму — это соединить таблицу с самой собой, используя >=
в DocNum, который объединит предыдущие значения, которые затем можно суммировать, чтобы вычесть из текущего значения.
Я вижу здесь недостаток, если значение Available_SOH когда-либо будет изменено так, чтобы оно было ниже, чем первый документ минус объединенный предыдущий Required_SOH, так ли это когда-либо?
select
current.DocNum
,current.Source
,current.Loc
,current.Bin
,current.Item
,current.Required_SOH
,max(history.Available_SOH) - sum(history.Required_SOH) as Available_SOH
from #TempSOH as current
inner join #TempSOH as history on current.Source = history.Source
and current.Loc = history.Loc
and current.Bin = history.Bin
and current.Item = history.Item
and current.DocNum >= history.DocNum
group by
current.DocNum
,current.Source
,current.Loc
,current.Bin
,current.Item
,current.Required_SOH
,current.Available_SOH
Доступная стоимость рассчитывается как разница между
текущий итог для Availible_SOH
и
текущий итог для Ruquired_SOH без текущей строки — поскольку «доступен» для текущей строки.
См. пример
select *
,sum(Available_SOH)over(partition by Source, Loc, Bin, Item ORDER BY DocNum)
-sum(Required_SOH)over(partition by Source, Loc, Bin, Item ORDER BY DocNum)
+Required_SOH newAvailable_SOH
from #TempSOH
Там выражение
,sum(Available_SOH)over(partition by Source, Loc, Bin, Item ORDER BY DocNum)
-sum(Required_SOH)over(partition by Source, Loc, Bin, Item ORDER BY DocNum)
+Required_SOH newAvailable_SOH
равен
,sum(Available_SOH)over(partition by Source, Loc, Bin, Item ORDER BY DocNum)
-coalesce(sum(Required_SOH)over(partition by Source, Loc, Bin, Item ORDER BY DocNum
rows between unbounded preceding and 1 preceding)
,0)
Это именно то, что я искал! сработало отлично, большое спасибо!