复杂的 SQL 服务器 CTE 情况:查找根 parent 记录

A complicated SQL Server CTE situation: Finding the root parent record

这篇文章很长,但我将重要的内容加粗了。

所以我在网上(包括此处)搜索了关于在 sql server 2012 中构建合适的 CTE 的内容。我发现了各种关于如何构建 CTE 的解决方案,但从我注意到的情况来看(尚未发现)是一个具有内部连接的 CTE。我不确定这是否会改变游戏规则,但我的尝试让我陷入困境。因此,我将我的困境带到这个社区,希望有人有见识。我会尽我所能帮助大家理解我的出发点。

在我的工作中,我的任务是创建一个全新的警报确认 GUI,因为我们的软件 (Wonderware Archestra IDE) 附带的默认 GUI 太小,我们的操作员无法在他们的触摸屏上使用.我应该用你会在酒吧看到的触摸屏菜单系统重新发明轮子。操作员将 select 发出警报并单击确认。并弹出一个充满确认选项的 GUI。

我正在创建的 GUI 会弹出并在顶部显示一个按钮列表,显示与警报关联的工厂(根 parent)中每个部分的名称。单击该按钮将打开其下方的按钮列表,无论是警报确认原因还是子文件夹,它们都可以出于更具体的原因进一步深入。我完成了第二部分,我正在微调第一部分,其中图形将查询数据库以检索所有关联的 parent 记录到警报。

以下为查询原文:

SELECT DISTINCT urg.reas_grp_desc, urg.reas_grp_id, urg.parent_reas_grp_id
FROM [MESDB].[dbo].[util_reas_link] url  
inner join [MESDB].[dbo].[util_reas] ur on ur.reas_cd = url.reas_cd  
inner join [MESDB].[dbo].[util_reas_grp] urg on urg.reas_grp_id = ur.reas_grp_id    
where url.raw_reas_cd = @reasoncode

原查询结果:

reas_grp_desc   reas_grp_id parent_reas_grp_id
General         0           NULL
TestSubFolder9  129         128

[util_reas_link] 是 table 包含所有可能的警报(主键)和所有关联的确认原因(外键)。

[util_reas] 是 table,它包含所有可能的确认原因(主键)和工厂的所有相关部分和子部分(外部钥匙)。

[util_reas_grp] 是 table 包含工厂的所有部分和子部分(主键)并且每个记录都有一个主组 ID 和 parent 组 ID。如果记录在 parent 组 ID 中为空,则它是该部分的根 parent。

此查询一直有效,直到工厂需要更多更细等级的确认原因。原因是旧查询只检查谁是该确认原因的 parent 和 grandparent 文件夹。现在深度可以达到 9 个文件夹的深度。

我修改后的查询(和困境)是这样的:

;WITH CTE_REASON_GROUP
AS
(

SELECT urg.reas_grp_desc, urg.reas_grp_id, urg.parent_reas_grp_id,  1 as Lvl, urg.reas_grp_id as [RootGroupId]
FROM [MESDB].[dbo].[util_reas_grp] urg
where urg.parent_reas_grp_id is null
UNION ALL 
SELECT urg.reas_grp_desc, urg.reas_grp_id, urg.parent_reas_grp_id, cterg.Lvl+1 as Lvl, cterg.RootGroupId
FROM [MESDB].[dbo].[util_reas_link] url  
inner join [MESDB].[dbo].[util_reas] ur on ur.reas_cd = url.reas_cd  
inner join [MESDB].[dbo].[util_reas_grp] urg on urg.reas_grp_id = ur.reas_grp_id  
inner join CTE_REASON_GROUP cterg on cterg.reas_grp_id = urg.parent_reas_grp_id 
where url.raw_reas_cd = @reasoncode

)
SELECT DISTINCT * FROM CTE_REASON_GROUP      order by reas_grp_id

我知道发生了什么。我知道锚点正在检索所有根 parents。而且我知道第二个内部查询(原始查询与 link CTE_REASON_GROUP 的另一个内部连接)只检索与@reasoncode 和 CTE_REASON_GROUP 的 reas_grp_id 没有结果。这是因为从上面看到只有两条记录被检索到,而且没有一个 parent_reas_grp_id 与锚点检索到的记录 reas_grp_id 匹配。

结果就是主播的结果:

reas_grp_desc       reas_grp_id parent_reas_grp_id  Lvl RootGroupId
General             0           NULL                1   0
Pouring Station     1           NULL                1   1
Melting             2           NULL                1   2
Spray Booth         4           NULL                1   4
Core Room           10          NULL                1   10
Splitter            11          NULL                1   11
Stamper             12          NULL                1   12
Hot Wheel Grinding  13          NULL                1   13
Hub Cutting         14          NULL                1   14
Heat Treat          21          NULL                1   21
Core Baker          25          NULL                1   25

我知道我接近答案了。但我似乎无法弥合 CTE 与我想要的结果之间的差距。从原始查询 General 我不必担心,因为它是一个根 parent,其中包含原因代码。然而,TestSubFolder9 是 9 个子文件夹,带有测试原因代码。它的根 parent 是 CoreRoom。

我要的结果是这样的,因为TestSubFolder9的根目录parent:

reas_grp_desc       reas_grp_id parent_reas_grp_id  Lvl RootGroupId
General             0           NULL                1   0
Core Room           10          NULL                1   10

虽然冗长,但我希望这能帮助这里的每个人理解我想要完成的事情以及我缺少什么拼图来获得我需要的记录。谢谢!

您应该像这样反转 CTE 以提升层次结构:

;WITH CTE_REASON_GROUP
AS
(
SELECT urg.reas_grp_desc, urg.reas_grp_id, urg.parent_reas_grp_id, 1 as Lvl, cterg.RootGroupId
FROM [MESDB].[dbo].[util_reas_link] url  
inner join [MESDB].[dbo].[util_reas] ur on ur.reas_cd = url.reas_cd  
inner join [MESDB].[dbo].[util_reas_grp] urg on urg.reas_grp_id = ur.reas_grp_id  
where url.raw_reas_cd = @reasoncode
UNION ALL 

SELECT urg.reas_grp_desc, urg.reas_grp_id, urg.parent_reas_grp_id,  cterg.Lvl+1 as Lvl, urg.reas_grp_id as [RootGroupId]
FROM [MESDB].[dbo].[util_reas_grp] urg
inner join CTE_REASON_GROUP cterg on urg.reas_grp_id = cterg.parent_reas_grp_id 
--where urg.parent_reas_grp_id is null

)
SELECT * FROM CTE_REASON_GROUP
order by lvl desc --reas_grp_id