用层次表选择多对多

时间:2018-07-04 15:32:45

标签: sql sql-server

   dbo.Tags
   ---------------
   [TagsId]

   dbo.TagsDetail 
   ----------------
   [TagsDetailId] 
   [TagsId]
   [TagsGroupId]

   dbo.TagsGroup (hierarchical table with 2 level)
   ----------------
   [TagsGroupId]
   [ParentId]


    Tags
    +--------+
    | Tagsld |
    +--------+
    | 1      |
    | 2      | 
    +--------+


    TagsDetails
    +-------------+-----------+
    | Tagsld      |TagsGroupId|
    +-------------+-----------+
    | 1           | 1         | 
    | 2           | 2         | 
    +-------------+-----------+

    TagsGroup
    +-------------+-----------+
    | TagsGroupId | ParentId  |
    +-------------+-----------+
    | 1           | null      | 
    | 2           | null      | 
    | 3           | 1         |
    +-------------+-----------+

输入TagGroupsId = 2 =>所有taggroup(1、2、3)

如何通过输入一个@TagsGroupId选择所有相关的TagGroupId?

我试图通过@TagsGroupId选择所有TagDetailIds来解决,所以我找到了所有TagIds并从TagIds中找到了。我找到了所有的TagsDetailIds,然后得到了所有相关的TagsGroupIds及其后代,并且在每个TagsGroupId上,我再次开始了循环。

我不知道可以在哪里停下来以确保已选择所有TagGroupID。

1 个答案:

答案 0 :(得分:1)

  

注意:通常不使用复数来完成操作-因此该列应被称为TagId而不是TagsId,而表应被称为TagGroup而不是TagsGroup。这样更容易。它没有任何作用,但这是每个人都使用的约定。

据我了解,标签组最多可以有两个父母,可以有孩子和孙子。

您可以在一个查询(包括子查询和联接)中完成所有操作,但我认为CTE会使逻辑更容易。

WITH Parent AS
(
   SELECT TD.TagId
   FROM TagGroup TG
   JOIN TagDetail ON TD.TagGroupId = TG.ParentId
   WHERE TG.TagGroupId = @TagGroupId
), GrandParent AS
(
   SELECT TD.TagId
   FROM TagGroup TG
   JOIN TagDetail ON TD.TagGroupId = TG.ParentId
   WHERE TG.TagGroupId = (SELECT TagId FROM Parent) 
), Child AS
(
   SELECT TD.TagId
   FROM TagGroup TG
   JOIN TagDetail ON TD.TagGroupId = TG.TagGroupId
   WHERE TG.ParentId = @TagGroupId 
), GrandChild AS
(
   SELECT TD.TagId
   FROM TagGroup TG
   JOIN TagDetail ON TD.TagGroupId = TG.TagGroupId
   WHERE TG.ParentId = (SELECT TagId FROM Child) 
)
SELECT TagId 
FROM Parent
UNION
SELECT TagId
FROM GrandParent
UNION
SELECT TagId
FROM Child
UNION
SELECT TagId
FROM GrandChild