我如何从间隔的内部文本构建带有 CTE 的嵌套树?

How can I build a nested tree with CTE from a spaced inner text?

给定以下 table 数据(从逗号分隔的组件列表导入数据)

[SQL CTE]
;WITH COMPONENTS(ID, TEXT, CHILD) AS 
(
   SELECT 
     ID,TEXT, (CASE WHEN PATINDEX(' %',TEXT)=1 THEN 1 ELSE 0 END)
   FROM tblComponents
) 
SELECT * FROM COMPONENTS

[TABLE DATA]
ID  |   TEXT        |   ISCHILD
------------------------------------------------
1   |   PARENT1     |   0
2   |   PARENT2     |   0
3   |     CHILD1    |   1
4   |     CHILD2    |   1

数据的间距标识上述CHILD1、CHILD2都是PARENT2的children。因为它们的开头有空格并且它们的顺序假定它们是 ID 2 的 children。

这可能吗?我已经 运行 查询 PATINDEX(' %',TEXT)=1 给我 ISCHILD。

注意:假设只有Parent->ManyChildren(不管TEXT有多少空格),没有grandchildren;我只对最初的关系感兴趣

[ORIGINAL DATA]
ID,COMPONENT,
44,"COMPONENT1 contains:",
45,"  CHILD1 ",
46,"  CHILD2   ",
47,"  CHILD3 ",

Expected/Needed 输出:

ID  |   TEXT        |   PARENT_ID
------------------------------------------------
1   |   PARENT1     |   0
2   |   PARENT2     |   0
3   |     CHILD1    |   2
4   |     CHILD2    |   2

您要 运行 遇到的一个大问题是,您正在按照 table 中记录的顺序对有关数据的信息进行编码。我可以向你保证,这只会导致死亡和毁灭。

值得庆幸的是,您确实有一个 "ID" 似乎可以在将记录写入文件系统的顺序之外维护数据的顺序,因此这是朝着正确方向迈出的一步。此外,您通过查找前导空格识别了 children。所以你在正确的轨道上。

下一步是确定Parent child人属于哪个。你可以这样做:

SELECT
    id,
    text,
    ischild,
    (
        SELECT TOP 1 id FROM Components WHERE isChild = 0 AND children.id > Components.id   ORDER BY id ASC
    ) AS parent_id

FROM components as children

如果层次结构比一层更深,并且您可以确定 child 连接到 parent 的唯一方法是通过前面的间距,那么您可以获得更多创意:

SELECT
    id,
    text,
    ischild,
    (
        SELECT TOP 1 id FROM Components
        WHERE 
            children.id > Components.id AND
            (len(Components.text) - len(replace(Components.text,' ',''))) < (len(children.text) - len(replace(children.text, ' ',''))) AND
            Components.isChild = 0
        ORDER BY id ASC
    ) AS parent_id

FROM components as children

对于最后一个,我们将遍历每条记录,然后寻找具有以下特征的最高 parent id:

  1. 一个 ID 小于我们正在查看的 child 记录
  2. 前导空格少于我们正在查看的 child 记录

此语句的记录集现在将具有 child 的 ID 和 parent 的 ID。如果 parent 的 id 是 NULL 那么我们就知道我们处于层次结构的根节点。

从这里您可以构建一个递归视图来查看层次结构路径、节点深度以及您想要从层次结构中挤出的任何其他内容:

WITH recursiveCTE
AS
(
    SELECT 
        id,
        text,
        parent_id,
        CAST(NULL as VARCHAR(500)) as path
        0 as depth
    FROM new_components_table
    WHERE parent_id IS NULL

    UNION ALL

    SELECT
        nct.id,
        nct.text,
        nct.parent_id,
        cte.path + '>' + nct.text as path,
        cte.depth + 1 as depth
    FROM
        recursiveCTE cte
        INNER JOIN new_components_table nct ON
            cte.id = nct.parent_id
)
SELECT id,text,parent_id, path, depth FROM recursiveCTE