T-Sql使用递归CTE

时间:2018-01-04 10:43:17

标签: sql-server tsql sql-server-2012 recursive-query

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

如果项目只有一组记录,则效果很好。例如项目号2000045(收据1,2,3等)。但是,如果我有一个多项目的表没有和收据没有这个查询不会工作。有人建议我使用光标迭代项目编号,但不确定。请帮忙。

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

1 个答案:

答案 0 :(得分:1)

除非我遗漏了某些内容,否则您需要做的就是从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
   )