Sql问题:获取父行后跟子行

Sql问题:获取父行后跟子行,sql,hierarchical,Sql,Hierarchical,id父\u id 10 20 3.2 40 5.1 60 我需要一个查询,该查询将返回父行parent_id=0,后跟其子行 第一父母 第一父母的所有子女 二亲 第二父母的所有子女 第三家长 第四亲 预期结果:按id排序 id父\u id 10第一家长 5.1第一父母的所有子女 20第二家长 3.2第二父母的所有子女 40第三方家长 60第四家长 我可以使用父母的联合,然后是所有的孩子 但这给了我先是父母,然后是孩子。 我需要父母和孩子 P>>据我所知,如果您所存储的所有都是父ID,则不能用一个

id父\u id

10

20

3.2

40

5.1

60

我需要一个查询,该查询将返回父行parent_id=0,后跟其子行

第一父母

第一父母的所有子女

二亲

第二父母的所有子女

第三家长

第四亲

预期结果:按id排序

id父\u id

10第一家长

5.1第一父母的所有子女

20第二家长

3.2第二父母的所有子女

40第三方家长

60第四家长

我可以使用父母的联合,然后是所有的孩子 但这给了我先是父母,然后是孩子。 我需要父母和孩子


P>>据我所知,如果您所存储的所有都是父ID,则不能用一个SQL语句来实现这一点。如果需要快速检索数据树,就必须考虑存储一个预序遍历。它比它听起来更容易,这里描述得很好:

据我所知,如果您所存储的所有都是父ID,则不能用一个SQL语句来实现这一点。如果需要快速检索数据树,就必须考虑存储一个预序遍历。这比听起来要简单,这里对它进行了很好的描述:

这里是一个示例解决方案,使用带有order by子句的union,但它不适用于深层嵌套

SELECT  p.id, 
        p.parent_id, 
        p.name,  
        p.id AS sequence
FROM topics AS p 
WHERE p.parent_id = 0
UNION 
SELECT  t.id, 
        t.parent_id, 
        t.name, 
        t.parent_id AS sequence
FROM topics AS t
WHERE t.parent_id <> 0
ORDER BY sequence, parent_id, name

下面是一个使用带有ORDERBY子句的union的示例解决方案,但它不适用于深层嵌套

SELECT  p.id, 
        p.parent_id, 
        p.name,  
        p.id AS sequence
FROM topics AS p 
WHERE p.parent_id = 0
UNION 
SELECT  t.id, 
        t.parent_id, 
        t.name, 
        t.parent_id AS sequence
FROM topics AS t
WHERE t.parent_id <> 0
ORDER BY sequence, parent_id, name

您将为此使用递归CTE:

WITH r AS 
 (SELECT id, 
    NULL AS parent_id, 
    CAST(right('000' + CAST(row_number() 
         OVER (table.id) AS varchar), 3) AS varchar(50))
  FROM table WHERE parent IS NULL

  UNION ALL

  SELECT table.id, table.parent_id, 
    CAST(r.ord + right('000' + CAST(row_number() 
         OVER (ORDER BY table.id) AS varchar), 3) AS varchar(50))
  FROM r JOIN table 
   ON table.parent = r.id)

 SELECT id 
 FROM r
 ORDER BY left(ord + '000000000000000000000000000000000', 36)
请注意,如果任何ID的值大于999,则此特定版本将中断,如果级别超过12级,则此版本将中断。如果这是您关心的问题,则需要调整各个位置的零数


可能有更好的方法,但这一种很有效。

对此,您可以使用递归CTE:

WITH r AS 
 (SELECT id, 
    NULL AS parent_id, 
    CAST(right('000' + CAST(row_number() 
         OVER (table.id) AS varchar), 3) AS varchar(50))
  FROM table WHERE parent IS NULL

  UNION ALL

  SELECT table.id, table.parent_id, 
    CAST(r.ord + right('000' + CAST(row_number() 
         OVER (ORDER BY table.id) AS varchar), 3) AS varchar(50))
  FROM r JOIN table 
   ON table.parent = r.id)

 SELECT id 
 FROM r
 ORDER BY left(ord + '000000000000000000000000000000000', 36)
请注意,如果任何ID的值大于999,则此特定版本将中断,如果级别超过12级,则此版本将中断。如果这是您关心的问题,则需要调整各个位置的零数


也许有更好的方法,但这一种有效。

replicate:@Projapati,为什么同一个问题要问两次?第一个问题的格式似乎不正确。不知道如何删除。抱歉重复。重复:@Projapati,为什么同一个问题重复两次?第一个问题似乎格式错误。不知道如何删除。对不起,重复了。你在这一点上完全错了。我只是对用于在联合后对结果进行排序的列做了一些更改。我得到了我需要的确切结果。这比我想象的要简单得多。谢谢您的评论。您是否愿意发布您的解决方案?以防万一将来有人也有同样的问题。。谢谢。这一点你完全错了。我只是对用于在联合后对结果进行排序的列做了一些更改。我得到了我需要的确切结果。这比我想象的要简单得多。谢谢您的评论。您是否愿意发布您的解决方案?以防万一将来有人也有同样的问题。。谢谢