最简单的方法来做一个recursion的自我join?

在SQL Server中执行recursion自连接最简单的方法是什么? 我有这样一张桌子:

PersonID | Initials | ParentID 1 CJ NULL 2 EB 1 3 MB 1 4 SW 2 5 YT NULL 6 IS 5 

而且我希望能够获得仅与特定人员开始相关的logging。 所以如果我通过PersonID = 1请求CJ的层次结构,我会得到:

 PersonID | Initials | ParentID 1 CJ NULL 2 EB 1 3 MB 1 4 SW 2 

而对于EB的我会得到:

 PersonID | Initials | ParentID 2 EB 1 4 SW 2 

我有点卡住了这个可以不能想到除了基于一堆连接的固定深度响应之外如何做到这一点。 这样做会发生,因为我们不会有很多关卡,但是我想正确地做。

谢谢! 克里斯。

 WITH q AS ( SELECT * FROM mytable WHERE ParentID IS NULL -- this condition defines the ultimate ancestors in your chain, change it as appropriate UNION ALL SELECT m.* FROM mytable m JOIN q ON m.parentID = q.PersonID ) SELECT * FROM q 

通过添加sorting条件,您可以保留树的顺序:

 WITH q AS ( SELECT m.*, CAST(ROW_NUMBER() OVER (ORDER BY m.PersonId) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN AS bc FROM mytable m WHERE ParentID IS NULL UNION ALL SELECT m.*, q.bc + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY m.ParentID ORDER BY m.PersonID) AS VARCHAR(MAX)) COLLATE Latin1_General_BIN FROM mytable m JOIN q ON m.parentID = q.PersonID ) SELECT * FROM q ORDER BY bc 

通过改变ORDER BY条件,你可以改变兄弟姐妹的顺序。

使用CTE,你可以这样做

 DECLARE @Table TABLE( PersonID INT, Initials VARCHAR(20), ParentID INT ) INSERT INTO @Table SELECT 1,'CJ',NULL INSERT INTO @Table SELECT 2,'EB',1 INSERT INTO @Table SELECT 3,'MB',1 INSERT INTO @Table SELECT 4,'SW',2 INSERT INTO @Table SELECT 5,'YT',NULL INSERT INTO @Table SELECT 6,'IS',5 DECLARE @PersonID INT SELECT @PersonID = 1 ;WITH Selects AS ( SELECT * FROM @Table WHERE PersonID = @PersonID UNION ALL SELECT t.* FROM @Table t INNER JOIN Selects s ON t.ParentID = s.PersonID ) SELECT * FROm Selects 

Quassnoi查询与大表的更改。 父母有更多的孩子,然后10:forms为str(5)row_number()

用q AS 
         (
         SELECT m。*,CAST(str(ROW_NUMBER()OVER(ORDER BY m.ordernum),5)AS VARCHAR(MAX))COLLATE Latin1_General_BIN AS bc
        从#tm
         WHERE ParentID = 0
        联盟所有
         SELECT m。*,q.bc +'。'  + str(ROW_NUMBER()OVER(PARTITION BY m.ParentID ORDER BY m.ordernum),5)COLLATE Latin1_General_BIN
        从#tm
        joinq
        开m.parentID = q.DBID
         )
select *
从q
 ORDER BY
        公元前

SQL 2005或更高版本,CTE是所示示例的标准方式。

SQL 2000,你可以使用UDF来做到这一点 –

 CREATE FUNCTION udfPersonAndChildren ( @PersonID int ) RETURNS @t TABLE (personid int, initials nchar(10), parentid int null) AS begin insert into @t select * from people p where personID=@PersonID while @@rowcount > 0 begin insert into @t select p.* from people p inner join @to on p.parentid=o.personid left join @t o2 on p.personid=o2.personid where o2.personid is null end return end 

(这将在2005年工作,这不是标准的做法,也就是说,如果你发现更简单的工作方式,运行它)

如果你确实需要在SQL7中这样做,你可以在一个存储过程中粗略地做上述事情,但是不能从中select–SQL7不支持UDF。

Interesting Posts