复杂的SQL Server CTE情况:查找根父记录

时间:2016-05-13 16:06:44

标签: sql-server database common-table-expression

这是一个漫长的过程,但是我把重要的东西加上了粗体。

所以我已经在网上(包括这里)搜索了在sql server 2012中构建一个正确的CTE。我已经找到了各种解决方案,解决了如何构建一个但是从我注意到的(并且还是发现)是一个内部连接的CTE。我不确定这是否会改变游戏规则,但我对它的尝试却让我陷入困境。因此,我将这种困境带到这个社区,希望有人有洞察力。我会努力尽可能地帮助每个人了解我的来源。

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

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

以下是原始查询:

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] 是包含所有可能的警报(主键)和所有相关的确认原因(外键)的表。

[util_reas] 是包含所有可能的确认原因(主键)以及工厂的所有相关部分和子部分(外键)的表。

[util_reas_grp] 是包含工厂的所有部分和子部分的表(主键),每条记录都有一个主要组ID和一个父组ID。如果父组id中的记录为null,则它是该节的根父级。

此查询有效,直到工厂想要更精细等级的更多确认原因。原因是旧查询仅检查谁是该确认原因的父和祖父文件夹。现在深度可以远远超过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

我知道发生了什么事。我知道主播正在检索所有的根父母。并且我知道第二个内部查询(具有另一个内部联接的原始查询以链接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到我想要的结果的差距。从原始查询一般我不必担心,因为它是一个带有原因码的根父。然而,TestSubFolder9是9个子文件夹,带有测试原因代码。它的根父是CoreRoom。

我正在寻找的结果是因为TestSubFolder9的根父母:

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

虽然冗长,但我希望这有助于每个人在这里了解我想要完成什么,以及我缺少哪些拼图来获取我需要的记录。谢谢!

1 个答案:

答案 0 :(得分:0)

你应该像这样反转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