Реализация логики FIFO - PullRequest
       43

Реализация логики FIFO

0 голосов
/ 26 декабря 2018

В довольно простой базе данных (Firebird 3.0) у меня есть таблица инвентаря с полями, относящимися к продуктам:

Покупка

QTY     PRICE   VALUE    Date
10      10      100      1.12.2018
25      9       225      5.12.2018
30      8       240      12.12.2018
50      7       350      14.12.2018
100     6       600      22.12.2018

Всего (КОЛИЧЕСТВО, ЦЕНА, ЗНАЧЕНИЕ): 215, 40, 1515

Здесь ПРОДАНО КОЛИЧЕСТВО равно 150, и мне нужно суммировать (значение) для самых ранних записей в "ПОКУПКАХ" до sum(QTY) = SOLD QTY.

1 Ответ

0 голосов
/ 26 декабря 2018

Эту проблему легко решить, используя Оконные агрегаты , поддерживаемые в Firebird 3:

select *
  ,case when cumulative_qty <= sold_qty then qty
        when sold_qty-(cumulative_qty - qty) < 0 then 0
        else sold_qty-(cumulative_qty - qty)
   end as qty_sold
  ,case when cumulative_qty <= sold_qty then qty
        when sold_qty-(cumulative_qty - qty) < 0 then 0
        else sold_qty-(cumulative_qty - qty)
   end * price as value_sold
from
 (
   select *
     ,150 as sold_qty
      -- cumulative sum of quantity in stock (FIFO)
     ,sum(qty) over (order by date rows unbounded preceding) as cumulative_qty
   from tab
 ) as dt
;

Теперь вы можете вычислить сумму:

select 
  sum(case when cumulative_qty <= sold_qty then qty
           when sold_qty-(cumulative_qty - qty) < 0 then 0
           else sold_qty-(cumulative_qty - qty)
      end) as qty_sold
  ,sum(case when cumulative_qty <= sold_qty then qty
            when sold_qty-(cumulative_qty - qty) < 0 then 0
            else sold_qty-(cumulative_qty - qty)
       end * price) as value_sold
from
 (
   select *
     ,150 as sold_qty
      -- cumulative sum of quantity in stock (FIFO)
     ,sum(qty) over (order by date rows unbounded preceding) as cumulative_qty
   from tab
 ) as dt
;

См. db <> fiddle (с использованием Postgres, но синтаксис Firebird должен быть таким же)

...