13

いくつかの 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

購入された順序で販売されていると仮定して、SQL 経由で販売マージンを見つけるにはどうすればよいですか? たとえば、SKU 123 のマージンは

30*1 + 28*3 + 25*2 - 20.15*5 - 17.50*1

2 個は 17.50 で購入し、1 個は 15.00 で購入し、売れ残っています。

4

4 に答える 4

7

良い質問。私が取っているアプローチは、総売上高を計算することです。次に、累積購入額を計算し、それらを特別なロジックと組み合わせて、組み合わせに適した算術を取得します。

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

注:このクエリはテストしていないため、構文エラーが発生する可能性があります。

于 2013-01-31T19:53:04.553 に答える
1

周囲の設定

    declare @purchased table (id int,sku int,dt date,price money,qty int)
    declare @sold table (id int,sku int,dt date,price money,qty int)

    insert into @purchased
    values( 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)

    insert into @sold
    values(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)

sqlserverソリューションは...

    with cte_sold as (select sku,sum(qty) as qty, SUM(qty*price) as total_value
                      from @sold
                      group by sku
                      )
    ,cte_purchased as (select id,sku,price,qty 
                       from @purchased
                       union all select id,sku,price,qty-1 as qty 
                       from cte_purchased
                       where qty>1
                    )
    ,cte_purchased_ordened as(select ROW_NUMBER() over (partition by sku order by id,qty) as buy_order
                                    ,sku
                                    ,price
                                    ,1 as qty
                              from cte_purchased 
    )

    select P.sku
          ,S.total_value - SUM(case when P.buy_order <= S.qty then P.price else 0 end) as margin
    from cte_purchased_ordened P
    left outer join cte_sold S
    on S.sku = P.sku
    group by P.sku,S.total_value,S.qty

達成された結果セット

    sku margin
    123 45,75
    456 20,00

問題の説明のsku123の例と同じ結果...

30 * 1 + 28 * 3 + 25 * 2-20.15 * 5-17.50 * 1 = 45.75

于 2013-01-31T19:45:45.357 に答える
0

クエリ内のMySQL変数を変更するため、これは本当に恐ろしいことですが、一種の動作をします(そして、3つのステートメントを取ります)。

select
  @income := sum(price*qty) as income,
  @num_bought := cast(sum(qty) as unsigned) as units
from sale
where sku = 123
;

select
  @expense := sum(expense) as expense,
  sum(units) as units
from (select
  price * least(@num_bought, qty) as expense,
  least(@num_bought, qty) as units,
  @num_bought := @num_bought - least(@num_bought, qty)
from purchase
where sku = 123 and @num_bought > 0
order by po_id
) as a
;

select round(@income - @expense, 2) as profit_margin;
于 2013-01-31T22:27:04.873 に答える
-1

これは Oracle クエリですが、どの SQL でも機能するはずです。これは簡略化されており、必要な計算がすべて含まれているわけではありません。自分で追加できます。合計が 17.50*1 ではなく 17.50*3 とわずかに異なることがわかります。

SELECT po_sku AS sku, po_total, sale_total, (po_total-sale_total) Margin
  FROM
 (
  SELECT SUM(price*qty) po_total, sku po_sku
    FROM stack_test
  GROUP BY sku
 ) a,
 (
  SELECT SUM(price*qty) sale_total, sku sale_sku
    FROM stack_test_sale
   GROUP BY sku
 ) b
 WHERE po_sku = sale_sku
 /

SKU     PO_TOTAL    SALE_TOTAL  MARGIN
---------------------------------------------------
123     168.25      164         4.25
456     420         80          340

必要に応じて、SKU ごとにパーティションを追加することもできます。

SUM(price*qty) OVER (PARTITION BY sku ORDER BY sku)
于 2013-01-31T21:36:48.073 に答える