我有一个表dbo.TrueMarginCalc,我需要执行该表以根据日期计算加权成本。我也有此电子表格,它说明了我需要做的事情。数据库中的表就是这样。
在此表下面的图像中,按[日期] ASC排序,我这样计算第一个实例:
然后我需要使用前一天的“加权真实费用”再次递归计算,依此类推:
我的代码是这样的:
CREATE TABLE dbo.TrueMarginCalc
(
[WHS] varchar(3),
[PRODUCT] varchar(5),
[TRANS DATE] DATE,
[RECEIPTS] INT,
[TRUE COST] NUMERIC(18,8),
[RUNNING_SALES] INT,
)
INSERT INTO dbo.TrueMarginCalc
SELECT
'350','54710','2018-09-06',42,0.7128,52 UNION ALL SELECT
'350','54710','2018-09-07',42,0.7154,61 UNION ALL SELECT
'350','54710','2018-09-08',42,0.715 ,42 UNION ALL SELECT
'350','54710','2018-09-10',0 ,0 ,37 UNION ALL SELECT
'350','54710','2018-09-11',42,0.7124,44 UNION ALL SELECT
'350','54710','2018-09-12',42,0.7125,42 UNION ALL SELECT
'350','54710','2018-09-13',42,0.7147,77 UNION ALL SELECT
'350','54710','2018-09-14',0 ,0 ,35 UNION ALL SELECT
'350','54710','2018-09-15',42,0.7123,47 UNION ALL SELECT
'350','54710','2018-09-17',0 ,0 ,22 UNION ALL SELECT
'350','54710','2018-09-18',42,0.7183,45 UNION ALL SELECT
'350','54710','2018-09-19',42,0.71 ,42 UNION ALL SELECT
'350','54710','2018-09-20',42,0.7124,56 UNION ALL SELECT
'350','54710','2018-09-21',0 ,0 ,10 UNION ALL SELECT
'350','54710','2018-09-22',42,0.7124,43 UNION ALL SELECT
'350','54710','2018-09-24',0 ,0 ,0 UNION ALL SELECT
'350','54710','2018-09-25',42,0.71 ,41 UNION ALL SELECT
'350','54710','2018-09-26',42,0.71 ,54
select *, (Running_Sales*[TRUE COST])/NULLIF(Running_Sales,0) As [Weighted True Cost]
FROM dbo.TrueMarginCalc order by [TRANS DATE]
所有这些操作就是计算第一天的加权真实费用。是否需要某种游标或递归才能在T-SQL中执行此操作?
;
WITH CTE AS (
select ROW_NUMBER() OVER (PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE]) AS RNK, WHS,PRODUCT,[TRANS DATE], [RECEIPTS], [TRUE COST], RUNNING_SALES
, CAST((Running_Sales*[TRUE COST])/NULLIF(Running_Sales,0) AS MONEY) As [Weighted True Cost] FROM dbo.TrueMarginCalc
UNION ALL
select ROW_NUMBER() OVER (PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE]) AS RNK, WHS,PRODUCT,[TRANS DATE], [RECEIPTS], [TRUE COST], RUNNING_SALES
, CAST((Receipts*[TRUE COST])+([Weighted True Cost] * Running_Sales)/(Receipts+Running_Sales) AS MONEY) AS [Weighted True Cost] FROM CTE
WHERE RNK = RNK - 1
)
SELECT * FROM CTE
ORDER BY [TRANS DATE] asc
以上代码从理论上讲是我所需要的,但是我肯定会错误地使用终止符,因为它会产生与递归CTE锚点完全相同的计算。
答案 0 :(得分:1)
您可以为此使用递归cte,例如:
WITH cte AS (
-- numbering is required for rcte
SELECT *, ROW_NUMBER() OVER (PARTITION BY WHS, PRODUCT ORDER BY TRANS_DATE) AS rn
FROM TrueMarginCalc
), rcte AS (
-- base row for each partition
SELECT *, CAST(TRUE_COST * RUNNING_SALES / TRUE_COST AS DECIMAL(18, 8)) AS WTC
FROM cte AS base
WHERE rn = 1
UNION ALL
-- next row for each partition
SELECT curr.*, CAST(prev.WTC * curr.RUNNING_SALES / curr.TRUE_COST AS DECIMAL(18, 8))
FROM cte AS curr
INNER JOIN rcte AS prev ON curr.WHS = prev.WHS AND curr.rn = prev.rn + 1
)
SELECT *
FROM rcte
不幸的是,公式不完整,但是上面的查询显示了如何访问当前行和上一个迭代中的列。
答案 1 :(得分:0)
我对公式不是100%,但是您可以尝试一下。
SELECT WHS, PRODUCT, [TRANS DATE], RECEIPTS, [TRUE COST], [RUNNING_SALES]
, (
CASE [TRUE COST]
WHEN 0.0 THEN LAG([True Cost]) OVER(PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE])
ELSE (COALESCE( LAG([True Cost]) OVER(PARTITION BY WHS, PRODUCT ORDER BY [TRANS DATE]), [TRUE COST] ) + [True Cost]) / 2
END
) AS [WeightedTrueCost]
FROM dbo.TrueMarginCalc