简单的CTE递归查询

时间:2018-02-28 15:12:49

标签: sql sql-server common-table-expression recursive-query

我很抱歉打扰这么简单的问题,但我决定学习CTE递归查询,即使在确定了很多源和线程之后我也无法查询我的查询。所以我谦卑地要求指出我的错误。

以下是我要查询的表的一部分:

ID        ContainerInstanceID  ItemID      ContentContainerInstanceID
--------- -------------------- ----------- --------------------------
73        40                   NULL        41        
69        40                   23885       NULL
68        40                   29683       NULL
67        40                   29686       NULL
72        41                   27392       NULL
71        41                   29235       NULL
70        41                   29213       NULL

我收集了这个简单的CTE查询:

;WITH ContainerContent_CTE(InstanceID,ItemID,ContentContainerInstanceID) AS
 (
  -- ROOT set accordig to input parameter
  SELECT ContainerInstanceID,SCA.ItemID,SCA.ContentContainerInstanceID 
  FROM StockContainerAssignments as SCA 
  WHERE SCA.ContainerInstanceID = 40  -- input parameter

  UNION ALL

  -- recursive data
  SELECT ContainerInstanceID,SCA2.ItemID,SCA2.ContentContainerInstanceID 
  FROM ContainerContent_CTE AS CC
  JOIN StockContainerAssignments as SCA2 on CC.InstanceID = SCA2.ContentContainerInstanceID
  )
SELECT * FROM ContainerContent_CTE;

我要做的是采用顶级容器,在此示例中它具有ID = 40,这是我的输入参数。然后,我尝试通过将ContainerInstanceID与ContentContainerInstanceID相关联来连接其他级别。在我的例子中,它不是空行ar ID = 73.这应该在我的结果集中添加另外3行(所以它应该看起来类似于我上面给出的示例数据),但我仍然只获得顶级行:

InstanceID   ItemID  ContentContainerInstanceID
-----------  ----------- --------------------------
40           29686       NULL
40           29683       NULL
40           23885       NULL
40           NULL        41        

我很欣赏能帮助我绊倒这个主题的提示。

3 个答案:

答案 0 :(得分:2)

这对我有用

declare @t table (id int, instance int, container int);
insert into @t values 
               (73, 40, 41)       
             , (69, 40, NULL)
             , (68, 40, NULL)
             , (67, 40, NULL)
             , (72, 41, NULL)
             , (71, 41, NULL)
             , (70, 41, NULL);
select * from @t;
with cte as 
( select t.id, t.instance, t.container
  from @t t
  where t.instance = 40 
  union all 
  select t.id, t.instance, t.container
  from cte 
  join @t t 
    on t.instance = cte.container
)
select * from cte;

答案 1 :(得分:2)

你刚才有一些不合适的东西。这应该适合你。

with ContainerContent_CTE as
(
    select SCA.ContainerInstanceID
        ,SCA.ItemID
        ,SCA.ContentContainerInstanceID 
    FROM StockContainerAssignments as SCA 
    WHERE SCA.ContainerInstanceID = 40  -- input parameter

    UNION ALL 

    select SCA.ContainerInstanceID
        ,SCA.ItemID
        ,SCA.ContentContainerInstanceID 
    FROM StockContainerAssignments as SCA
    inner join ContainerContent_CTE cte on cte.ContentContainerInstanceID = SCA.ContainerInstanceID
)

select *
from ContainerContent_CTE

答案 2 :(得分:0)

正如预期的那样,一个愚蠢的小错误在某个方面 - 在ON条款中,我将父母和孩子与相同的ID对连接起来。因为我只学习CTE,所以很难看到我。这是固定的(参考):

;WITH ContainerContent_CTE(InstanceID,temID,ContentContainerInstanceID) AS
 (
  -- ROOT set accordig to input parameter
  SELECT ContainerInstanceID,SCA.ItemID,SCA.ContentContainerInstanceID 
  FROM StockContainerAssignments as SCA 
  WHERE SCA.ContainerInstanceID = 40  -- input parameter

  UNION ALL

  -- recursive data
  SELECT ContainerInstanceID,SCA2.ItemID,SCA2.ContentContainerInstanceID 
  FROM ContainerContent_CTE AS CC
  INNER JOIN StockContainerAssignments as SCA2 on CC.ContentContainerInstanceID = SCA2.ContainerInstanceID)
SELECT * FROM ContainerContent_CTE;

感谢您的建议。