2011-10-20 32 views
9

我一直在研究CTE,試圖確定是否有可能用訂單數量遞歸更新庫存數量記錄,直到訂單數量被消耗。CTE - 遞歸更新數量,直到消耗總量

下面是表和記錄:

CREATE TABLE [dbo].[myOrder](
    [Account] [float] NOT NULL, 
    [Item] [float] NOT NULL, 
    [Quantity] [float] NOT NULL 
) ON [PRIMARY] 

insert into dbo.myOrder values (12345, 1, 50) 

CREATE TABLE [dbo].[myInventory](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Account] [float] NOT NULL, 
    [InvDate] [numeric](18, 0) NOT NULL, 
    [Item] [float] NOT NULL, 
    [Quantity] [float] NOT NULL, 
    [QuantitySold] [float] NOT NULL 
) ON [PRIMARY] 

insert into dbo.myInventory values (12345, 111287, 1, 45, 40) 
insert into dbo.myInventory values (12345, 111290, 1, 40, 0) 
insert into dbo.myInventory values (12345, 111290, 1, 12, 0) 
insert into dbo.myInventory values (12345, 111291, 1, 25, 0) 

在myOrder表中的記錄指示的順序爲帳戶12345要創建的項目#1,數量50:

Account Item Quantity 
------- ---- -------- 
12345 1 50 

庫存表格顯示,我們手頭有大量第一項用於賬戶12345:

ID Account InvDate Item Quantity QuantitySold 
-- ------- ------- ---- -------- ------------ 
1 12345 111287 1 45  40 
2 12345 111290 1 40  0 
3 12345 111290 1 12  0 
4 12345 111291 1 25  0 

goa l將開始在訂單數量50中插入庫存記錄,直到消耗全部50。庫存記錄按InvDate列中的值排序。記錄1有5個剩餘數量(45 - 40 = 5),這將使我們剩下45個用於訂單。

ID Account InvDate Item Quantity QuantitySold 
-- ------- ------- ---- -------- ------------ 
1 12345 111287 1 45  45 
2 12345 111290 1 40  40 
3 12345 111290 1 12  5 
4 12345 111291 1 25  0 

注:庫存表存儲QuantitySold,不QuantityRemaining,所以你必須做當查詢完成庫存記錄是這樣的記錄2可以消耗40記錄3可以消耗在過去5數學(Quantity - QuantitySold)來確定每個庫存記錄剩餘多少數量。

我幾乎無處與CTE。我已經找到了很多用於選擇你的CTE的2個部分的例子 - 初始化部分和遞歸部分UNION在一起。我可以用光標寫這個,但我認爲可以用CTE來做,我想學習如何。

如果有人可以證實這是可能的CTE或解釋如何設置CTE,我會很感激。謝謝!

+3

+1對於DDL腳本 –

+3

偏離主題,但爲什麼您使用* float *來建模數量?你真的*想要*能夠讓項目2的1.47E-19剩餘庫存嗎? –

+0

達米安 - 公平的問題。我的公司使用JDEdwards作爲其ERP,其數量領域使用浮動。考慮到這一點,我製作了這些表格。啊,遺留數據庫! – Brian

回答

10
[email protected] table mimics inserted virtual table from AFTER INSERT triggers on [dbo].[myOrder] table 
DECLARE @inserted TABLE 
(
    [Account] [float] NOT NULL, 
    [Item] [float] NOT NULL, 
    [Quantity] [float] NOT NULL 
); 

INSERT @inserted 
VALUES (12345, 1, 50); 

WITH CteRowNumber 
AS 
(
    SELECT inv.ID 
      ,inv.Account 
      ,inv.Item 
      ,inv.Quantity 
      ,inv.QuantitySold 
      ,i.Quantity QuantityOrdered 
      ,ROW_NUMBER() OVER(PARTITION BY inv.Account,inv.Item ORDER BY inv.ID ASC) RowNumber 
    FROM myInventory inv 
    INNER JOIN @inserted i ON inv.Account = i.Account 
    AND  inv.Item = i.Item 
    WHERE inv.Quantity > inv.QuantitySold 
), CteRecursive 
AS 
(
    SELECT a.ID 
      ,a.Account 
      ,a.Item 
      ,a.RowNumber 
      ,CASE 
       WHEN a.Quantity - a.QuantitySold < a.QuantityOrdered THEN a.Quantity - a.QuantitySold 
       ELSE a.QuantityOrdered 
      END QuantitySoldNew 
      ,CASE 
       WHEN a.Quantity - a.QuantitySold < a.QuantityOrdered THEN a.Quantity - a.QuantitySold 
       ELSE a.QuantityOrdered 
      END RunningTotal 
    FROM CteRowNumber a 
    WHERE a.RowNumber = 1 
    UNION ALL 
    SELECT crt.ID 
      ,crt.Account 
      ,crt.Item 
      ,crt.RowNumber 
      ,CASE 
       WHEN prev.RunningTotal + (crt.Quantity - crt.QuantitySold) < crt.QuantityOrdered THEN crt.Quantity - crt.QuantitySold 
       ELSE crt.QuantityOrdered - prev.RunningTotal 
      END QuantitySoldNew 
      ,CASE 
       WHEN prev.RunningTotal + (crt.Quantity - crt.QuantitySold) < crt.QuantityOrdered THEN prev.RunningTotal + (crt.Quantity - crt.QuantitySold) 
       ELSE crt.QuantityOrdered 
      END RunningTotal 
    FROM CteRecursive prev 
    INNER JOIN CteRowNumber crt ON prev.Account = crt.Account 
    AND  prev.Item = crt.Item 
    AND  prev.RowNumber + 1 = crt.RowNumber 
    WHERE prev.RunningTotal < crt.QuantityOrdered 
) 
SELECT cte.ID 
     ,cte.Account 
     ,cte.Item 
     ,cte.QuantitySoldNew 
FROM CteRecursive cte; 
--or CteRecursive can be used to update QuantitySold column from [dbo].[myInventory] table 
--UPDATE myInventory 
--SET  QuantitySold = inv.QuantitySold + cte.QuantitySoldNew 
--FROM myInventory inv 
--INNER JOIN CteRecursive cte ON inv.ID = cte.ID; 
+0

波格丹,這太棒了!非常感謝你。我需要花一些時間研究你的查詢,以瞭解它正在做的一切,但它效果很好。看到它運行並正確使用訂單數量真的很酷。再次感謝! – Brian