Sql server 卡德克斯重建公司

Sql server 卡德克斯重建公司,sql-server,tsql,common-table-expression,window-functions,Sql Server,Tsql,Common Table Expression,Window Functions,我正在努力重建我的公司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

小贴士:如果你在问题中包含了预期的结果,那会很有帮助

这个通用表表达式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语句末尾添加分号后,可以对示例数据运行它

性能可能很差,因为您需要从第一行开始计算。添加列以维护QuantityOnHand和AveragragreUnitCost将允许您在新事务发生时(例如在触发器中)更新数据。请注意,更新和删除可能需要从头开始重新计算


一个更现代的解决方案将使用/,但我恰好又回到了SQL Server 2008 R2。

我忘了提到我正在使用Microsoft SQL Server 2012标准。测试数据处理得不错,请将预期结果添加为文本,并与itI一起解释。我确认此查询是我正在寻找的解决方案。比你好多了。我做了一些小改动,因为我必须使它适应数据库中的一些特定场景,但这个查询使这一切成为可能。再次感谢你@我很高兴它为你指明了写作的方向。接受回答是StackOverflow礼节的一部分。看,对不起。我是新发帖的问题。答案被接受。再次感谢!