T-Sql 使用递归 CTE 计算平均值

T-Sql Calculate averages using Recursive CTE

我有以下 table 并构建了一个递归 CTE 查询,该查询计算特定 [item no] 和第一张收据的股票平均价格,并使用该平均值计算后续平均值 i/e收据2,收据3直到结束。

如果项目只有一组记录,这很有效。例如项目编号 2000045(收据 1、2、3 等)。但是,如果我有多个项目编号和 receiptNo 的 table,则此查询将不起作用。有人建议我使用游标遍历项目编号但不确定。请帮忙。

CREATE TABLE [dbo].[AKTest](
[IntakeSellingPrice] [decimal](38, 20) NULL,
[IntakeSellingAmount] [decimal](38, 6) NULL,
[Item No_] [nvarchar](20) NOT NULL,
[Posting Date] [datetime] NOT NULL,
[PurchaseQty] [decimal](38, 20) NULL,
[ReceiptNo] [bigint] NULL,
[InventoryBalance] [decimal](38, 20) NOT NULL,
[NewBalance] [decimal](38, 20) NULL
) ON [PRIMARY]

GO
INSERT [dbo].[AKTest] ([IntakeSellingPrice], [IntakeSellingAmount], [Item No_], [Posting Date], [PurchaseQty], [ReceiptNo], [InventoryBalance], [NewBalance]) VALUES (CAST(75.00000000000000000000 AS Decimal(38, 20)), CAST(37500.000000 AS Decimal(38, 6)), N'2000045', CAST(0x0000A81F00000000 AS DateTime), CAST(500.00000000000000000000 AS Decimal(38, 20)), 1, CAST(0.00000000000000000000 AS Decimal(38, 20)), CAST(500.00000000000000000000 AS Decimal(38, 20)))
GO
INSERT [dbo].[AKTest] ([IntakeSellingPrice], [IntakeSellingAmount], [Item No_], [Posting Date], [PurchaseQty], [ReceiptNo], [InventoryBalance], [NewBalance]) VALUES (CAST(75.00000000000000000000 AS Decimal(38, 20)), CAST(163575.000000 AS Decimal(38, 6)), N'2000045', CAST(0x0000A82400000000 AS DateTime), CAST(2181.00000000000000000000 AS Decimal(38, 20)), 2, CAST(500.00000000000000000000 AS Decimal(38, 20)), CAST(2681.00000000000000000000 AS Decimal(38, 20)))
GO
INSERT [dbo].[AKTest] ([IntakeSellingPrice], [IntakeSellingAmount], [Item No_], [Posting Date], [PurchaseQty], [ReceiptNo], [InventoryBalance], [NewBalance]) VALUES (CAST(83.33000000000000000000 AS Decimal(38, 20)), CAST(55.555831 AS Decimal(38, 6)), N'2000045', CAST(0x0000A82B00000000 AS DateTime), CAST(0.66667000000000000000 AS Decimal(38, 20)), 3, CAST(2681.00000000000000000000 AS Decimal(38, 20)), CAST(2681.66667000000000000000 AS Decimal(38, 20)))
GO



;WITH   Testcte
AS     (
SELECT A.*, (
                (A.PurchaseQty * A.IntakeSellingPrice) 
                    + 
                    (A.InventoryBalance *  isnull(A2.IntakeSellingPrice, A.IntakeSellingPrice))
                ) /A.NewBalance [RunningAVG]

    from AKTest A
    left join AKTest A2 on A.[Item No_] = A2.[Item No_] and A.ReceiptNo = A2.ReceiptNo +1
    where A.ReceiptNo = 1 -- anchor member
    and A.[Item No_]='2000045'

UNION ALL

SELECT X.* , (
            (X.PurchaseQty * X.IntakeSellingPrice) 
            + 
            (X.InventoryBalance * X1.RunningAVG )
            ) /X.NewBalance [RunningAVG]
    from AKTest X
    join Testcte X1 on X.ReceiptNo = X1.ReceiptNo +1
    and X.[Item No_]='2000045'
   )
SELECT *
FROM   Testcte;

对于上述查询,结果的平均值是:

75.000000
75.000000
75.002070

除非我遗漏了什么,否则您需要做的就是从您的 cte 中删除硬编码的项目编号(and A.[Item No_]='2000045' 在锚部分,and A.[Item No_]='2000045' 在递归部分)和也只需加入项目编号的递归部分:

;WITH   Testcte
AS     (
SELECT A.*, (
                (A.PurchaseQty * A.IntakeSellingPrice) 
                    + 
                    (A.InventoryBalance *  isnull(A2.IntakeSellingPrice, A.IntakeSellingPrice))
                ) /A.NewBalance [RunningAVG]

    from AKTest A
    left join AKTest A2 on A.[Item No_] = A2.[Item No_] and A.ReceiptNo = A2.ReceiptNo +1
    where A.ReceiptNo = 1 -- anchor member
    -- and A.[Item No_]='2000045' -- removed this condition
UNION ALL

SELECT X.* , (
            (X.PurchaseQty * X.IntakeSellingPrice) 
            + 
            (X.InventoryBalance * X1.RunningAVG )
            ) /X.NewBalance [RunningAVG]
    from AKTest X
    join Testcte X1 on X.ReceiptNo = X1.ReceiptNo +1
    and X.[Item No_] = X1.[Item No_] -- this is instead of the next line (that's commeneted out)
    -- and X.[Item No_]='2000045' -- removed this as well
   )