如何获取自引用表的每条记录的所有子项

Posted

技术标签:

【中文标题】如何获取自引用表的每条记录的所有子项【英文标题】:How to get all child of each records of a self-referenced table 【发布时间】:2015-01-30 12:46:52 【问题描述】:

我有一张如下表:

身份证 |孩子ID |姓名 ---------------------- 1 空名称1 2 1 名称2 3 2 姓名3 4 3 名称4 5 4 姓名5 6 5 姓名6 7 6 姓名7 8 7 姓名8 9 8 姓名9 10 9 名称10 11 3 名称11

现在我想要一个查询,它可以为每个至少有一个孩子的记录获取所有可能的孩子,并返回一个像这样的 DataSet:

身份证 |家长 ID |姓名 |父母 ID ----------------------------------------- 1 NULL 名称1 11,10,9,8,7,6,5,4,3,2 2 1 名称2 11,10,9,8,7,6,5,4,3 3 2 名称3 11,10,9,8,7,6,5,4 4 3 名称4 10,9,8,7,6,5 5 4 名称5 10,9,8,7,6 6 5 姓名6 10,9,8,7 7 6 姓名7 10,9,8 8 7 姓名8 10,9 9 8 姓名9 10

【问题讨论】:

使用递归 CTE。 ***.com/questions/19914472/… 我之前回答***.com/questions/26030796/…987654322@的另一个例子 在原始表中,ID = 1 的父 ID 为空。在结果集中,ID = 1 的父 ID 为 11、10、9、8、7、6、5、4、3、2。这没有意义。 @Nightmaresux 抱歉,我编辑了问题,我的意思是结果表中的 childID 而不是 parentID @GiorgosBetsos 抱歉我编辑了这个问题,我的意思是结果表中的 childIDs 而不是 parentIDs 【参考方案1】:

使用这个查询。

更新结果: Fiddler Demo

    CREATE TABLE TABLE1 (ID INT, ParentID INT, NAME VARCHAR(10));
INSERT INTO TABLE1 VALUES(1, NULL, 'Name1');
INSERT INTO TABLE1 VALUES(2, 1, 'Name2');
INSERT INTO TABLE1 VALUES(3, 2, 'Name3');
INSERT INTO TABLE1 VALUES(4, 3, 'Name4');
INSERT INTO TABLE1 VALUES(5, 4, 'Name5');
INSERT INTO TABLE1 VALUES(6, 5, 'Name6');
INSERT INTO TABLE1 VALUES(7, 6, 'Name7');
INSERT INTO TABLE1 VALUES(8, 7, 'Name8');
INSERT INTO TABLE1 VALUES(9, 8, 'Name9');
INSERT INTO TABLE1 VALUES(10, 9, 'Name10');
INSERT INTO TABLE1 VALUES(11, 3, 'Name11');

  SELECT ID, ParentID , Name, Child = STUFF((
          SELECT ',' + CAST(B.ID AS VARCHAR(100)) FROm TABLE1 AS B 
          WHERE ISNULL(A.ID, 0) < B.ID AND B.ID NOT IN(
              ISNULL((SELECT TOP 1 C.ID FROm TABLE1 AS C 
                      WHERE C.ParentID IN (
                            SELECT ParentID FROM TABLE1 WHERE ID <= A.ID) 
                      ORDER BY C.ID DESC), 0))  
          ORDER BY B.ID DESC 
          FOR XML PATH (''), type).value('.', 'varchar(max)'), 1,1,'')
 FROm TABLE1 AS A

旧结果:

 SELECT ID, ParentID , Name, ParentIDs = STUFF((
  SELECT ',' + CAST(B.ID AS VARCHAR(100)) FROm MyTable AS B 
  WHERE ISNULL(A.ID, 0) < B.ID ORDER BY B.ID  DESC FOR XML PATH (''), type).value('.',
          'varchar(max)'), 1,1,'')
 FROm MyTable AS A

【讨论】:

不是正确答案。您只是将较高的值分配为较低值的子项。 5 - 10,9,8,7,6 是孩子。但你的答案显示 - 11,10,9,8,7,6 @Veera:我已经更新了结果。检查并回复状态。 @Kumar 非常感谢我的朋友,您的旧查询与我的理想结果不符,但您的更新工作正常。无论如何谢谢【参考方案2】:

你可以试试这个:

  SELECT a.*,x.ParentIDs
    FROM YourTable a
    CROSS APPLY (SELECT STUFF(CAST((SELECT ',' + CONVERT(VARCHAR,b.ID) 
    FROM YourTable b WHERE b.ID > a.ID AND ISNULL(b.ParentID,0) > ISNULL(a.ParentID,0) ORDER BY ID DESC
    FOR XML PATH(''), TYPE) AS VARCHAR(MAX)),1,1,'') AS ParentIDs ) x
    WHERE x.ParentIDs IS NOT NULL

【讨论】:

以上是关于如何获取自引用表的每条记录的所有子项的主要内容,如果未能解决你的问题,请参考以下文章

如何循环遍历表的所有行? (MySQL)

通过比较sql server中同一张表的每条记录返回重复

如何获取 Core Data 实体中一行的 ID,以便以后可以引用它?

如何从外键表中检索值?

如何为 Oracle 11g 中分层表的每条记录分配父组 ID?

如何获取表的记录