基于先进先出定价计算利润

Dav*_*nor 11 mysql sql sql-server

假设我有一些SKU的购买和销售数据:

po_id | sku | purchase_date    | price | qty
----------------------------------------------
    1 | 123 | 2013-01-01 12:25 | 20.15 |   5
    2 | 123 | 2013-05-01 15:45 | 17.50 |   3
    3 | 123 | 2013-05-02 12:00 | 15.00 |   1
    4 | 456 | 2013-06-10 16:00 | 60.00 |   7

sale_id | sku | sale_date        | price | qty
------------------------------------------------
      1 | 123 | 2013-01-15 11:00 | 30.00 |   1
      2 | 123 | 2013-01-20 14:00 | 28.00 |   3
      3 | 123 | 2013-05-10 15:00 | 25.00 |   2
      4 | 456 | 2013-06-11 12:00 | 80.00 |   1
Run Code Online (Sandbox Code Playgroud)

如何通过SQL找到销售保证金,假设它们按照购买的顺序出售?例如,sku 123的余量是

30*1 + 28*3 + 25*2 - 20.15*5 - 17.50*1
Run Code Online (Sandbox Code Playgroud)

其中2个是在17.50购买,1个在15.00购买,未售出.

Gor*_*off 6

好问题.我采取的方法是计算总销售额.然后计算累积购买量,并将它们与特殊逻辑组合以获得组合的正确算术:

select s.sku,
       (MarginPos - SUM(case when s.totalqty < p.cumeqty - p.qty then p.price * p.qty
                             when s.totalqty between p.cumeqty - p.qty and p.qty
                             then s.price * (s.totalqty - (p.cumeqty - p.qty))
                             else 0
                        end)
       ) as Margin
from (select s.sku, SUM(price*qty) as MarginPos, SUM(qty) as totalqty
      from sales s
     ) s left outer join
     (select p.*,
             (select SUM(p.qty) from purchase p2 where p2.sku = p.sku and p2.sale_id <= p.sale_id
             ) as cumeqty
      from purchase s
     )
     on s.sku = p.sku
group by s.sku, MarginPos
Run Code Online (Sandbox Code Playgroud)

注意:我没有测试过此查询,因此可能存在语法错误.

  • 注意:费用SUM可简化为:`SUM(price*GREATEST(LEAST(qty,totalqty - (cumeqty - qty)),0))`不需要case语句. (2认同)