2016-04-28 58 views
1

請參閱下面的DDL:遞歸SQL查詢來識別

CREATE TABLE #MasterChild (MasterID decimal(25,0), ChildID decimal(25,0), ChildCreTime datetime) 
insert into #MasterChild values (150021032000000173536533,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173571072,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173573651,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173574917,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173582487,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173604342,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173931636,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173935066,150021032000000173946207,'2016-04-22 13:27:30.483') 
insert into #MasterChild values (150021032000000173946207,150021032000000173952172,'2016-04-22 13:38:32.747') 
insert into #MasterChild values (150021032000000173946207,150021032000000173954415,'2016-04-22 13:43:28.120') 
insert into #MasterChild values (150021032000000173536533,150021032000000173954321,'2016-04-22 13:43:28.120') 
insert into #MasterChild values (150021032000000173954321,150021032000000173954319,'2016-04-22 13:43:28.120') 

和下面的SQL:

with GetAllMerges 
as 
(
select masterid,childid from #MasterChild where masterid=150021032000000173571072 and childid=150021032000000173946207 
union all 
select #MasterChild.masterid,#MasterChild.childid from #MasterChild inner join GetAllMerges 
on 
#MasterChild.childid=GetAllMerges.masterid 
or (#MasterChild.childid=GetAllMerges.childid and #MasterChild.masterid<>GetAllMerges.masterid) 
) 
select distinct masterid,childid from GetAllMerges 

我看到下面的錯誤:

Msg 530, Level 16, State 1, Line 1 
The statement terminated. The maximum recursion 100 has been exhausted before statement completion. 

這是爲什麼?我試圖展示所有關聯的孩子和主人。例如,如果主人1連接到孩子2,並且孩子2連接到主人3,並且主人3連接到孩子4並且孩子4連接到主人5,則連接人物1-5(所有孩子和主人都是人)。

回答

3

遞歸CTE的,你在這裏試圖做的暗示MAXRECURSION之前他們錯誤了。

您可以使用OPTION (MAXRECURSION n)指定想要的遞歸次數,其中n是介於0和32767之間的數字,其中0基本上表示無論需要多長時間才運行到競爭。

我不會告知你的情況

您的CTE不會出現有終止爲它的遞歸元素

An incorrectly composed recursive CTE may cause an infinite loop. For example, if the recursive member query definition returns the same values for both the parent and child columns, an infinite loop is created. To prevent an infinite loop, you can limit the number of recursion levels allowed for a particular statement by using the MAXRECURSION hint and a value between 0 and 32,767 in the OPTION clause of the INSERT, UPDATE, DELETE, or SELECT statement. This lets you control the execution of the statement until you resolve the code problem that is creating the loop. The server-wide default is 100. When 0 is specified, no limit is applied. Only one MAXRECURSION value can be specified per statement.

(強調)

重在更改MAXRECURSION設置之前,首先正確終止遞歸CTE,然後編寫查詢。

+2

在大多數情況下 - 當遞歸CTE達到100的默認值,因此打破它不是一個'MAXRECURSION'的問題,而是一個錯誤遍歷代碼的問題:-)另一個常見問題是,如果最後一個孩子與t有關他的父母以CTE在圈子裏跑的方式...... – Shnugo

0

讓我看看,如果我理解你的方法:

你寫了(GetAllMerges),以顯示你想要的數據,裏面的功能回過頭來參考一下它遞歸?

==>#MasterChild.childid = GetAllMerges.masterid < ===

我覺得你只是建立一個無限循環。

我不知道爲什麼你不只是使用一段時間或做一段時間來通過鏈接的鍵?

此外,當表名稱很長時,您可以並應該使用別名。

+1

*我不知道爲什麼你不只是使用一段時間或做,而是一步步通過鏈接的鍵?*僅僅因爲遊標,循環和一步一步的方法是應該避免任何可能的事情?閱讀關於RBAR,基於行和基於集合...遞歸CTE是通過分級結構遍歷的好工具... – Shnugo

+1

@Shnugo雖然顯然是遞歸CTE是[隱藏的RBAR](http:// www。 sqlservercentral.com/articles/T-SQL/74118/) – Shaneis

+0

@Shaneis,我已經閱讀過這篇文章 - 很棒的一篇,如果你正在尋找一個櫃檯,但並不真正與此有關......很明顯,一個純粹的計數器,每增加1步,就會成爲最好的RBAR。但是層次結構將在每一步中處理集合。如果一個parentID下面有10個孩子,你將一次獲得所有10個孩子,等等......遍歷一個層次結構(在許多級聯連接中經典地完成)在任何情況下都是一個沉重的過程......最後但並非最不重要的是:A rCTE是** ad-hoc ** SQL,因此完全內聯(使用索引,統計信息,,,)。 – Shnugo

0

您應該切換childID的和parentId的在你的「內部聯接」這樣的:

試試吧

with GetAllMerges 
as 
(
select masterid,childid,1 AS RecLevel 
from #MasterChild 
where masterid=150021032000000173571072 and childid=150021032000000173946207 
union all 
select #MasterChild.masterid,#MasterChild.childid,GetAllMerges.RecLevel + 1 
from #MasterChild 
inner join GetAllMerges on #MasterChild.masterid=GetAllMerges.ChildID 
--or (#MasterChild.childid=GetAllMerges.childid and #MasterChild.masterid<>GetAllMerges.masterid) 
) 
select distinct masterid,childid from GetAllMerges 

我評論的or (#MasterChild...了,因爲這會產生錯誤...請描述一下你正努力實現...

+0

但是,我還需要返回那些childid是在另一行上掌握的。因此,您所評論的代碼行需要取消註釋。取消註釋會導致原始問題。 – w0051977

+0

@ w0051977如果我正確理解你,這將是你不應該包括在遞歸CTE中的東西。只需向外部選擇添加一個連接幷包含這些行。你可能'DISTINCT'這是爲了避免doublettes – Shnugo

+0

我不相信我可以這樣做,因爲外部聯接是遞歸的。例如,主設備1鏈接到子設備2,子設備2鏈接到主設備3,主設備3鏈接到子設備4等。 – w0051977