用于返回包含值的最近父级的SQL查询

时间:2016-09-07 09:43:23

标签: sql sql-server tsql

我在SQL中有以下两个表。第一个表是ID,Parents和OwnerGroup的层次结构。第二个表是每个OwnerGroup中的成员集合。任务是在包含实际成员的层次结构中向上返回最近的OwnerGroup。

底部的SQL查询是我的查询的简化版本,它返回ID为1-4的正确成员,但对于ID 5和6,它返回一个空结果,因为MemberInOwnerGroup不包含OwnerGroup ='的值C'。在这种情况下,查询应继续遍历Product表并在OwnerGroup ='B'中获得结果。

任何帮助将不胜感激!

产品

------------------------------
| ID | ParentID | OwnerGroup |
------------------------------
| 1  |          |     A      |
| 2  |     1    |            |  
| 3  |     2    |     B      |
| 4  |     3    |            |
| 5  |     4    |     C      |
| 6  |     5    |            |
------------------------------

MemberInOwnerGroup

-----------------------
| OwnerGroup | Member |
-----------------------
|     A      | Alice  |
|     A      | Bob    |
|     B      | Dan    |
|     C      |        |
-----------------------

返回会员的SQL查询

WITH Hierarchy(ID, ParentID, OwnerGroup, NearestOwnerGroup)
AS
(
    SELECT ID, ParentID,OwnerGroup,CAST(OwnerGroup AS VARCHAR(MAX))
        FROM Product
        WHERE ParentID IS NULL    
    UNION ALL
    SELECT NextGeneration.ID, NextGeneration.ParentID,NextGeneration.OwnerGroup,
    CAST(CASE WHEN NextGeneration.OwnerGroup not like ''
        THEN(CAST(NextGeneration.OwnerGroup AS VARCHAR(MAX)))
        ELSE(Parent.NearestOwnerGroup)
    END AS VARCHAR(MAX))
        FROM Product AS NextGeneration
        INNER JOIN Hierarchy AS Parent ON NextGeneration.ParentID = Parent.ID    
)
SELECT Member FROM MemberInOwnerGroup WHERE OwnerGroup IN
(
    SELECT Hierarchy.NearestOwnerGroup 
        FROM Hierarchy
        WHERE Hierarchy.ID = '6'
)

不同ID的预期结果应为以下

--------------------
| ID | Member      |
--------------------
|  1 | Alice, Bob  | 
|  2 | Alice, Bob  |
|  3 | Dan         |
|  4 | Dan         |
|  4 | Dan         |
|  6 | Dan         |
--------------------

1 个答案:

答案 0 :(得分:0)

我在MemberInOwnerGroup表的联接中添加了返回组成员的表(如果为空,则返回ParentGroup)。这会在cte中创建重复行,这些行由生成的where exists语句中的select处理。

根据数据集的大小,这可能会导致性能问题:

with Hierarchy as
(
     select ID
           ,ParentID
           ,OwnerGroup
           ,cast(OwnerGroup as varchar(max)) as NearestOwnerGroup
     from Product
     where ParentID is null

     union all

     select NextGeneration.ID
           ,NextGeneration.ParentID
           ,NextGeneration.OwnerGroup
           ,cast(case when GroupMember.Member = '' then Parent.NearestOwnerGroup else GroupMember.OwnerGroup end as varchar(max)) as NearestOwnerGroup
     from Product as NextGeneration
        inner join Hierarchy as Parent
            on NextGeneration.ParentID = Parent.ID

        inner join (select OwnerGroup
                        ,Member
                    from MemberInOwnerGroup
                    ) GroupMember
            on GroupMember.OwnerGroup = case when NextGeneration.OwnerGroup = '' then Parent.OwnerGroup else NextGeneration.OwnerGroup end
)
select m.Member
from MemberInOwnerGroup m
where exists (select null
                from Hierarchy h
                where h.NearestOwnerGroup = m.OwnerGroup
                    and h.ID = '6'
                )