2017-09-22 131 views
1

我正試圖重建我的公司kardex。我需要使用「平均成本方法」,該平均成本方法應該考慮每個交易在其特定日期時間的平均成本。重建公司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標準版 –

+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

對不起。我是新發布的問題。接受答案。再次感謝! –