Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2008 递归查询中的SQL Server更新_Sql Server 2008_Recursion_Sql Update_Common Table Expression - Fatal编程技术网

Sql server 2008 递归查询中的SQL Server更新

Sql server 2008 递归查询中的SQL Server更新,sql-server-2008,recursion,sql-update,common-table-expression,Sql Server 2008,Recursion,Sql Update,Common Table Expression,我正在使用Microsoft SQL Server 2008,并试图通过递归查询实现与本文非常类似的功能: 当然,我试图简化事情;希望我已经以一种明确的方式这样做了。我的桌子看起来像这样: Parent Child A A A B B D D H D I A C C E E C E J E K C F C G A B D

我正在使用Microsoft SQL Server 2008,并试图通过递归查询实现与本文非常类似的功能:

当然,我试图简化事情;希望我已经以一种明确的方式这样做了。我的桌子看起来像这样:

Parent  Child
A       A
A       B
B       D
D       H
D       I
A       C
C       E
E       C
E       J
E       K
C       F
C       G
A
    B
        D
            H
            I
    C
        E
            C
            J
            K
        F
        G
从视觉上看,这些关系如下所示:

Parent  Child
A       A
A       B
B       D
D       H
D       I
A       C
C       E
E       C
E       J
E       K
C       F
C       G
A
    B
        D
            H
            I
    C
        E
            C
            J
            K
        F
        G
我需要在表中创建一个新列,该列表示子实体到顶层的路径(在本例中为a):

这里的折痕以及父子关系可能不是这里使用的术语的原因可以从实体C中看出,它既是实体E的父对象,也是子对象,这导致了一个无休止的递归循环

我的想法是更新递归循环中的链值,并限制对链列中具有空值的实体的递归调用。其思想是仅在第一次遇到实体时递归实体。我所做的将不起作用,我不确定如何将更新集成到递归调用中:

WITH r(parent,child,mychain)
AS
(
    SELECT parent, child, child AS myChain 
    FROM myTable 
    WHERE parent = 'A' AND
    parent <> child AND
    chain IS NULL
    UNION ALL
    SELECT v.parent, v.child, myChain + ',' + v.child AS myChain 
    FROM myTable v
    INNER JOIN r ON r.child = v.parent
    WHERE v.parent <> v.child
)
UPDATE myTable
SET chain = r.myChain
FROM myTable AS c
JOIN r ON c.ID = r.ID
对我如何做到这一点有什么建议吗

提前谢谢

编辑:

也许我有点过于简单化了。因为父列和子列的实际值相当长(大约20多个字符),所以我确实需要使用记录ID创建一个链,并将其作为值的对象。我修改了Simon的建议,如下所示。这让我非常接近;但是,C->E记录不会得到输出(所有记录最终都应该用链更新)。这可能无关紧要;我还在努力克服它

with r as
(
    SELECT id, parent, child, 
      CAST( id AS VARCHAR(1024) ) AS CHAIN,
      0 as level
    FROM myTable 
    WHERE id = '1' 


    UNION ALL
    SELECT c.id, c.parent, c.child, 
      cast( (r.CHAIN + ',' + CAST( c.id AS varchar(10)) ) AS varchar(1024)) AS CHAIN,
      r.level + 1 as level
    FROM myTable c
    JOIN r
      ON r.child = c.parent
    WHERE c.parent != c.child AND r.parent != c.child

)
select * from r order by r.level, r.parent, r.child; 
试试这个:

with r as
(
    SELECT parent, child, 
      CAST( (parent + ',' + child) AS VARCHAR(10)) AS chain, 
      0 as level
    FROM myTable 
    WHERE parent = 'A' 
    AND parent != child

    UNION ALL
    SELECT c.parent, c.child, 
      cast((r.chain + ',' + c.child) as varchar(10)) AS chain, 
      r.level + 1 as level
    FROM myTable c
    JOIN r
      ON r.child = c.parent
    WHERE r.chain NOT LIKE '%,' + c.child + ',%'

)
select * 
from r 
order by r.level, r.parent, r.child; 

查看:

您可能可以删除强制类型转换。SQL fiddle似乎需要它们,但我认为SQL server不需要。Simon,感谢您的回复。我想你正在接近我。我已经成功地在一些顶级实体上对我的真实数据运行了这个,但是在达到我设置的5000个递归的限制后,我有其他的超时。我仍在努力弄清楚达到这个极限是否有意义。那个么你们一定有更深的循环。上面的代码通过“WHERE c.parent!=c.child和r.parent!=c.child”添加了对任何循环长度的检查来防止像c=>e=>c这样的循环。我想你只需要一个简单的用例。它确实有效,它回答了最初的问题,所以我将把它标记为已回答。不过我要注意,我无法让它使用ID而不是子值来构建链(因为在附加链时,我们有子值,但没有它的ID)。谢谢你的帮助,西蒙!见下文。这对你有用吗?