SQL递归CTE - 公共表表达式'CTE'的递归成员具有多个递归引用

时间:2015-12-17 22:08:44

标签: sql-server tsql

我需要能够在执行CTE期间“回顾”。使用下面的示例数据,我需要返回一个额外的列,它代表BalanceDate列的余额。因此,rowid 6将返回30,因为这是截至2015年6月6日的余额。 Rowid 9将返回80,因为这是最接近2015年9月30日的最后一条记录。当我尝试将CTE用作派生表时,我收到错误

  

Msg 253,Level 16,State 1,Procedure   公用表表达式'CTE'的递归成员具有多个递归引用。

--Sample data
CREATE TABLE #TEMP
(RowID int null,
 TranDate date null,
 Amount int null,
 BalanceDate date null);


 INSERT INTO #TEMP (RowID,TranDate, Amount, BalanceDate)
 SELECT 1,'1/15/2015',10,null
UNION ALL
 SELECT 2,'2/18/2015',10,null
UNION ALL
 SELECT 3,'3/6/2015',10,null
UNION ALL
 SELECT 4,'6/1/2015',10,null
UNION ALL
 SELECT 5,'6/18/2015',10,null
UNION ALL
 SELECT 6,'7/31/2015',10,'3/6/2015'
UNION ALL
 SELECT 7,'8/2/2015',10,null
UNION ALL
 SELECT 8,'9/13/2015',10,null
UNION ALL
 SELECT 9,'11/15/2015',10,'9/30/2015';

with CTE  
as  
( SELECT RowID, TranDate, Amount, Balance=Amount, BalanceDate FROM #TEMP WHERE RowID = 1
 UNION ALL
  SELECT #TEMP.RowID,#TEMP.TranDate, #TEMP.Amount, Balance = #TEMP.Amount + CTE.Balance, #TEMP.BalanceDate
  FROM #TEMP
  INNER JOIN CTE on #Temp.RowID = CTE.RowID + 1
)
SELECT * FROM CTE;

1 个答案:

答案 0 :(得分:0)

我通常会避免使用递归CTE,除非您需要使用它们(例如,找到父母和孩子)。而不是使用递归CTE,你可以做这样的事情来得到你想要的东西:

编辑:

如果有负数,这将产生正确的结果。

SELECT RowID, T1.TranDate, Amount 
    , (SELECT SUM(Amount) FROM #TEMP WHERE TranDate <= T1.TranDate) Balance
    , BalanceDate
    , (SELECT SUM(Amount) FROM #TEMP WHERE TranDate <= T1.BalanceDate) BalanceToDate
FROM #TEMP T1

编辑了之前的其他查询,使其不那么混乱。

使用原始递归CTE:

; WITH CTE AS  
( 
    SELECT RowID, TranDate, Amount, Balance=Amount, BalanceDate 
    FROM TEMP 
    WHERE RowID = 1
    UNION ALL
    SELECT TEMP.RowID,TEMP.TranDate, TEMP.Amount, Balance = TEMP.Amount + CTE.Balance, TEMP.BalanceDate
    FROM TEMP
    JOIN CTE on Temp.RowID = CTE.RowID + 1
)
SELECT C.RowID, C.TranDate, C.Amount, C.Balance, C.BalanceDate
    , (SELECT SUM(Amount) FROM CTE WHERE TranDate <= C.BalanceDate) BalanceToDate
FROM CTE C