【发布时间】:2015-12-17 19:14:49
【问题描述】:
我有一个 CTE 来显示 2 个表(父表和子表)的依赖关系树。 存在导致循环依赖的数据问题,从而引发 Max Recursion level 错误。 即
Table: Parent
Id
ItemId
Table: Child
Id
ParentId
ItemId
Example Circular Ref data
Table: Parent
Id ItemId
1 A
2 B
Table: Child
Id ParentId ItemId
1 1 B
2 2 A
这些表中有数千行。如何编写查询以识别违规参考?或者有没有办法设置最大递归级别,一旦命中就会停止 CTE 而不是抛出错误......然后我可以查看结果并识别问题子项。
WITH Recursive_CTE AS
(
SELECT
ItemId,
CAST(ItemDescription AS varchar(100)) AS ItemDescription,
Qty,
CAST(ParentItemId AS SmallInt) AS ParentItemId,
CAST(ItemId AS varchar(100)) AS ParentGroupItemId,
CAST(' -' AS varchar(100)) AS LVL,
CAST(ItemId AS varchar(100)) AS HierarchyItem,
CAST(SKU AS varchar(100)) AS HierarchySKU,
CAST(ItemDescription AS varchar(100)) AS HierarchyName,
0 AS RecursionLevel
FROM dbo.vw_BOM AS child
WHERE (ParentItemId = 0)
--and ItemId = @BOMHeaderItemId
UNION ALL
SELECT
child.ItemId,
CAST(parent.LVL + child.ItemDescription AS varchar(100)) AS ItemDescription,
child.Qty,
CAST(child.ParentItemId AS SmallInt) AS ParentItemId,
parent.ParentGroupItemId,
CAST(' -' + parent.LVL AS varchar(100)) AS LVL,
CAST(parent.HierarchyItem + ':' + CAST(child.ItemId AS varchar(100)) AS varchar(100)) AS HierarchyItem,
CAST(parent.HierarchySKU + ':' + CAST(child.SKU AS varchar(100)) AS varchar(100)) AS HierarchySKU,
CAST(parent.HierarchyName + '/' + CAST(child.ItemDescription AS varchar(100)) AS varchar(100)) AS HierarchyName,
parent.RecursionLevel + 1 AS RecursionLevel
FROM Recursive_CTE AS parent INNER JOIN
dbo.vw_BOM AS child ON child.ParentItemId = parent.ItemId
)
SELECT
Recursive_CTE_1.RecursionLevel,
Recursive_CTE_1.ParentGroupItemId,
Recursive_CTE_1.ParentItemId,
Recursive_CTE_1.ItemId,
Recursive_CTE_1.Qty,
DATALENGTH(Recursive_CTE_1.LVL) AS LVLLength,
Recursive_CTE_1.ItemDescription,
item.SKU,
item.OnHandQty,
item.AllocQty,
item.AvailableQty,
item.ToBeReceivedQty,
item.AvailableWFutureQty,
Recursive_CTE_1.HierarchyItem,
Recursive_CTE_1.HierarchySKU,
Recursive_CTE_1.HierarchyName
FROM Recursive_CTE AS Recursive_CTE_1 INNER JOIN
dbo.vw_ItemInventorySummary AS item ON Recursive_CTE_1.ItemId = item.Id
ORDER BY Recursive_CTE_1.HierarchySKU
option (maxrecursion 200)
视图 vw_BOM
SELECT dbo.BillOfMaterialHeader.Id AS Id, dbo.BillOfMaterialHeader.ItemId AS ItemId, 0 AS ParentItemId, FGItems.SKU AS SKU, FGItems.SKU + N': ' + FGItems.ShortDescription AS ItemDescription,
dbo.BillOfMaterialHeader.Quantity AS Qty
FROM dbo.BillOfMaterialHeader INNER JOIN
dbo.Items AS FGItems ON dbo.BillOfMaterialHeader.ItemId = FGItems.Id
UNION ALL
SELECT dbo.BillOfMaterialDetail.Id AS Id, dbo.BillOfMaterialDetail.ItemId AS ItemId, BOMHdr.ItemId AS ParentItemId, RMItems.SKU AS SKU, RMItems.SKU + N': ' + RMItems.ShortDescription AS ItemDescription,
dbo.BillOfMaterialDetail.Quantity AS Qty
FROM dbo.Items AS RMItems INNER JOIN
dbo.BillOfMaterialDetail ON RMItems.Id = dbo.BillOfMaterialDetail.ItemId INNER JOIN
dbo.BillOfMaterialHeader BOMHdr ON dbo.BillOfMaterialDetail.BillOfMaterialHeaderId = BOMHdr.Id
更新
Tab 的回答为我指明了正确的方向。我在 vw_BOM 中使用了扁平的父子表,然后根据 Tab 的答案将其连接到自身,这向我显示了父表和子表中 6 个项目具有相同项目 ID 的位置。 像这样:
SELECT dbo.vw_BOM.SKU AS ParentSKU, vw_BOM_1.SKU AS ChildSKU
FROM dbo.vw_BOM INNER JOIN
dbo.vw_BOM AS vw_BOM_1 ON dbo.vw_BOM.ItemId = vw_BOM_1.ParentItemId AND dbo.vw_BOM.ParentItemId = vw_BOM_1.ItemId
【问题讨论】:
-
你能发布你的表结构和当前查询吗?我无法想象您是如何从两个表的父子结构中获取最大递归错误的。
-
@TabAlleman Tab,我添加了表结构。让我知道这是否有意义。
-
@ChadRichardson,当您实际上看到该错误时,您还可以看到选择的结果,您最终会看到哪些行给您带来了问题。
-
@GiorgiNakeuri 感谢 Giorgi,但在 SSMS 中不适合我,结果选项卡没有任何行,并且消息选项卡显示最大递归错误。
-
@ChadRichardson,你能显示查询吗?
标签: sql-server sql-server-2012 common-table-expression