如何在 SQL Server 2012 中递归查询多对多关系

How to recursively query for many to many relationships in SQL Server 2012

我在 SQL 2012 年有一个 table,它通过连接 table 与自身建立多对多关系。布局如下

我指的多对多关系是Currency_Dependency。

我想做的是进行一个递归查询,以树形方式显示所有依赖关系,以便每个关系都用一个数字表示,该数字显示距离所选主要货币项目还有多少步作为一个数字标识它在哪个分支上。我希望,如果可能的话,这个查询是双向的,显示它依赖的所有货币项目(父货币项目),以及所有依赖它的货币项目(子货币项目)。我有一个双向查询都只显示第一层。

SELECT curr.Model AS 'Root Currency Item', cur2.Model AS 'Child Currency Item', cur3.Model AS 'Parent Currency Item'
FROM dbo.Currency curr
FULL JOIN dbo.Currency_Dependency cdep
ON curr.CurrencyId = cdep.CurrencyId
FULL JOIN dbo.Currency cur2
ON cdep.DependencyId = cur2.CurrencyId
FULL JOIN dbo.Currency_Dependency cdep2
ON curr.CurrencyId = cdep2.DependencyId
FULL JOIN dbo.Currency cur3
ON cdep2.CurrencyId = cur3.CurrencyId
WHERE curr.Status = 1 AND NOT(cur2.Model IS null AND cur3.Model IS null)

产生这些结果

所以我想为父项和子项依赖项添加额外的列,其中的数字表示从根货币项开始的步骤数。我希望这是有道理的。

这样的查询可以吗?我知道一个常见的 table 表达式是用于递归查询的东西,但到目前为止我读到的所有内容都非常希腊化(我是计算机编程专业的二年级学生)

如果您能帮上忙,请告诉我!非常感谢!

没有示例数据我无法确定,但我认为这就是您所追求的:

;with cte as (
-- anchor elements: where curr.Status = 1 and not a dependent
  select 
      CurrencyId
    , Model
    , ParentId     = null
    , ParentModel  = convert(varchar(128),'')
    , Root         = curr.Model
    , [Level]      = convert(int,0)
    , [Path]       = convert(varchar(512),Model)
  from dbo.Currency as curr  
  where curr.Status = 1
    /* anchors do not depend on any other currency */
    and not exists (
      select 1 
      from dbo.Currency_Dependency i
      where curr.CurrencyId = i.DependencyId
      )
  -- recursion begins here
  union all 
  select 
      CurrencyId   = c.CurrencyId
    , Model        = c.Model
    , ParentId     = p.CurrencyId
    , ParentModel  = convert(varchar(128),p.Model)
    , Root         = p.Root
    , [Level]      = p.[Level] + 1
    , [Path]       = convert(varchar(512),p.[Path] + ' > ' + c.Model)
  from dbo.Currency as c
    inner join dbo.Currency_Dependency as dep
      on c.CurrencyId = dep.DependencyId
    inner join cte as p 
      on dep.CurrencyId = p.CurrencyId
)
select * from cte