2017-09-22 13 views
1

私は会社kardexを再構築しようとしています。特定の日時での各トランザクションの平均コストを考慮する「Average Cost Method」を使用する必要があります。再構築会社kardex

すべての着信/出庫トランザクション(すべての移動)を含む簡単なテーブルがあります。

すべての着信トランザクション(購入)は、対応する請求書から単価を徴収するため、正しく価格設定されています。

問題: すべての販売取引(出荷在庫)には単価がありません(これらのコストを再構築する必要があるため)。 私はカーソルを使うことができると知っていますが、私たちは皆そこでパフォーマンスの問題について知っています。

私は自分自身を説明するために簡単なデータを用意しました。 すべての販売(発信トランザクション)にはコストがかかりません。単純なウィンドウ関数を使用することは、各行が以前の計算に依存するため役立たないと考えています。だから、前回の計算に基づいて計算する必要があるのですか?

DECLARE @Resultado TABLE (Row_ID BIGINT IDENTITY NOT NULL PRIMARY KEY, Inventory_Name VARCHAR(100), Transaction_Date DATETIME, DIRECTION BIT, Transaction_Name VARCHAR(100),Transaction_Quantity INT, Transaction_UnitCost NUMERIC(18,2), Transaction_Amount NUMERIC(18,2), AVERAGE_UNITCOST_AT_TRANSACTION_DATE NUMERIC(18,2)) 

INSERT INTO @Resultado (Inventory_Name , Transaction_Date , DIRECTION , Transaction_Name , Transaction_Quantity , Transaction_UnitCost, Transaction_Amount, AVERAGE_UNITCOST_AT_TRANSACTION_DATE) 
SELECT 'COMPUTER', '2017-01-01', 1, 'INCOMING PRODUCT; PRUCHASE', 100, 10, 100 * 10, 10 
UNION ALL SELECT 'COMPUTER', '2017-01-02', 1, 'INCOMING PRODUCT; PURCHASE', 105, 11, 105 * 11, 10.51 
UNION ALL SELECT 'COMPUTER', '2017-01-03', 1, 'INCOMING PRODUCT; PURCHASE', 110, 12, 110 * 12, 11.03 
UNION ALL SELECT 'COMPUTER', '2017-01-04', 0, 'OUTGOING PRODUCT; SALES', -200, NULL, NULL, NULL 
UNION ALL SELECT 'COMPUTER', '2017-01-05', 0, 'OUTGOING PRODUCT; SALES', -50, NULL, NULL, NULL 
UNION ALL SELECT 'COMPUTER', '2017-01-06', 1, 'INCOMING PRODUCT; PURCHASE', 110, 10, 110 * 10, NULL 
UNION ALL SELECT 'COMPUTER', '2017-01-07', 0, 'OUTGOING PRODUCT; SALES', -20, NULL, NULL, NULL 
UNION ALL SELECT 'COMPUTER', '2017-01-08', 0, 'OUTGOING PRODUCT; SALES', -20, NULL, NULL, NULL 
UNION ALL SELECT 'COMPUTER', '2017-01-09', 0, 'OUTGOING PRODUCT; SALES', -20, NULL, NULL, NULL 

SELECT * FROM @Resultado 
+0

私はMicrosoft SQL Server 2012 Standardを使用していることを忘れていました –

+1

テストデータでうまく動作します。予想通りの結果をテキストとして追加してください。 – TheGameiswar

答えて

1

ヒント:あなたの質問に予想される結果が含まれていれば役に立ちました。

この共通テーブル式(CTE)は、あなたが始める必要があります。

with CTE as (
    select Row_Id, Inventory_Name, Transaction_Date, Direction, Transaction_Name, 
    Transaction_Quantity, Transaction_UnitCost, 
    Transaction_Quantity as QuantityOnHand, 
    Transaction_UnitCost as AverageUnitCost 
    from @Resultado 
    where Direction = 1 and Row_Id = 1 -- Starting condition for your single product sample data. 
    union all 
    select R.Row_ID, R.Inventory_Name, R.Transaction_Date, R.Direction, R.Transaction_Name, 
    R.Transaction_Quantity, R.Transaction_UnitCost, 
    -- The TransactionQuantity is already signed, so there is no need to multiple it by (Direction * 2 - 1) . 
    CTE.QuantityOnHand + R.Transaction_Quantity, 
    -- My accounting is pretty rusty, but this should do some sort of useful averaging. 
    Cast(case 
     when R.Direction = 0 then CTE.AverageUnitCost -- Sales don't affect the average unit cost. 
     else (CTE.AverageUnitCost * CTE.QuantityOnHand + R.Transaction_UnitCost * R.Transaction_Quantity)/
     (CTE.QuantityOnHand + R.Transaction_Quantity) end 
     as Numeric(18,2)) 
    from CTE inner join 
     @Resultado as R on R.Row_Id = CTE.Row_Id + 1 -- Row by row. 
    ) 
    select Row_Id, Inventory_Name, Transaction_Date, Direction, Transaction_Name, Transaction_Quantity, Transaction_UnitCost, 
    QuantityOnHand, AverageUnitCost 
    from CTE; 

あなたのselect文の最後にセミコロンを追加した後、あなたのサンプルデータに対してそれを実行することができます。

最初の行から計算を開始する必要があるため、パフォーマンスが低下する可能性があります。 QuantityOnHandAveragreUnitCostを維持する列を追加すると、新しい取引が発生したときにデータを更新できます。トリガーで

最近のソリューションではLead/Lagが使用されますが、SQL Server 2008 R2に戻ってしまいます。

+0

私が探していた解決策です。あなたはほんの少しです。私はデータベースのいくつかの特定のシナリオにそれを適用する必要があるため、私はいくつかのマイナーな変更を行いましたが、このクエリはすべて可能にしました。再びありがとう! –

+0

@LuisGilbert私はそれがあなたの書き込み方向を指してうれしいです。回答を受け入れることは、StackOverflowのエチケットの一部です。 [回答を受け入れる方法は?](http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work)を参照してください。 – HABO

+0

申し訳ありません。私は新しい質問を投稿しています。回答が受け入れられました。再度、感謝します! –