【问题标题】:How to self JOIN recursively in SQL?如何在 SQL 中递归地自我加入?
【发布时间】:2011-03-29 02:53:11
【问题描述】:

我有一张桌子:

系列 ======== ID 系列名称 父系列ID

系列可以是“根”系列(ParentSeriesID 为 0 或 null),也可以有父系列。一个系列也可以向下几个级别,即它的 Parent 有一个 Parent,它有一个 Parent,等等。

如何通过 ID 和所有后代系列查询表以获取系列?

到目前为止我已经尝试过:

 SELECT child.*
 FROM Series parent JOIN Series child ON child.ParentSeriesID = parent.ID
 WHERE parent.ID = @ParentID

但这仅返回第一级子节点,我想要父节点和所有“下游”节点。我不知道如何从这里取得进展。

【问题讨论】:

    标签: sql sql-server-2005 tsql hierarchical-data


    【解决方案1】:

    我只是加强了 Thomas 的工作。如果你需要获取层次结构的深度和获取parentid这里是代码。

    这与 Thomas 的工作几乎相同。

    With Family As 
    ( 
        Select s.ID, s.ParentSeriesId, 0 as Depth
        From Series s
        Where ID = @ParentID <--- this was removed if you intend to get all hierarchy of the record. You can retain this if you want
      Union All 
         Select s2.ID, s2.ParentSeriesId < --- change to **Family.ParentID**, Depth + 1
         From Series s2
         Join Family 
             On Family.ID = s2.ParentSeriesId 
    ) 
     Select *
     From Family 
    

    就是这样。我知道为时已晚,但我希望遇到这种情况的任何人都可以帮助他们。感谢 Thomas 提供原始代码。 :)

    【讨论】:

      【解决方案2】:

      如果您使用的是 SQL Server 2005+,则可以使用公用表表达式

      With Family As 
      ( 
      Select s.ID, s.ParentSeriesId, 0 as Depth
      From Series s
      Where ID = @ParentID 
      Union All 
      Select s2.ID, s2.ParentSeriesId, Depth + 1
      From Series s2
          Join Family 
              On Family.ID = s2.ParentSeriesId 
      ) 
      Select *
      From Family 
      

      更多:

      Recursive Queries Using Common Table Expressions

      【讨论】:

      • 我修改了您的查询以使其正常工作,请将其放入我对您问题的编辑中。感谢您的帮助!
      • 有什么方法可以在非 ms sql server db 上执行此操作?我需要一种不使用 CTE 的更标准的方法。
      • @goku_da_master - 取决于你的意思。相同的代码在 Postgres、Oracle 和 DB2 上应该可以正常工作。公共表表达式是 SQL 规范的一部分,因此由多个供应商实现。但是,听起来您在问如何在不支持 CTE 的数据库(如 MySQL 或 MS Access)上实现相同的目标。答案取决于产品。
      【解决方案3】:

      利用 slq server 2005 及以后版本中的CTE 功能进行递归查询

      USE AdventureWorks
      GO
      WITH Emp_CTE AS (
      SELECT EmployeeID, ContactID, LoginID, ManagerID, Title, BirthDate
      FROM HumanResources.Employee
      WHERE ManagerID IS NULL
      UNION ALL
      SELECT e.EmployeeID, e.ContactID, e.LoginID, e.ManagerID, e.Title, e.BirthDate
      FROM HumanResources.Employee e
      INNER JOIN Emp_CTE ecte ON ecte.EmployeeID = e.ManagerID
      )
      SELECT *
      FROM Emp_CTE
      GO
      

      您可以在此处查看示例:

      SQL SERVER – Simple Example of Recursive CTE

      【讨论】:

      • cte = 公用表表达式!
      猜你喜欢
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      相关资源
      最近更新 更多