CTE 递归语句,带自连接,不带 id

Posted

技术标签:

【中文标题】CTE 递归语句,带自连接,不带 id【英文标题】:CTE Recursion statement with self join without ids 【发布时间】:2022-01-20 03:29:18 【问题描述】:

我必须拆分数据列并与员工和经理建立关系。

ManagerDetails

data employee manager
imp/imp2/imp3/imp4 imp2 notimp4
notimp1/notimp2/notimp3/notimp4 imp3 imp4

如果你观察下面的输出表,如果我取第一行,imp4imp3 的经理,imp3imp2 的经理,imp2imp 的经理,所以我需要建立如下所述的表。

第一行的预期输出:

data employee manager
imp/imp2/imp3/imp4 imp4
imp/imp2/imp3 imp4 imp3
imp/imp2 imp3 imp2
imp imp2 imp

我使用CTE将ManagerDetails的行与Link的引用分开并进行查询

DECLARE @separator varchar(1) = '/';
WITH rCTE AS(
    SELECT
       1 as [level] ,
       d.data,
       CHARINDEX(@separator, CONCAT(d.data, @separator)) AS Position
    FROM ManagerDetails d   
    UNION ALL
    SELECT
       r.[level] + 1,
       r.data,
       CHARINDEX(@separator, CONCAT(r.data, @separator), r.Position + 1) AS Position
    FROM rCTE r
    WHERE CHARINDEX(@separator, CONCAT(r.data, @separator), r.Position + 1) > 0
)
SELECT [level], SUBSTRING(CONCAT(data, @separator), 1, Position - 1) AS [Value]
FROM rCTE
ORDER BY [level], Position DESC
OPTION (MAXRECURSION 0)

通过上述查询,我​​能够按预期显示数据列,但无法按预期更改经理和员工列。

感谢任何形式的帮助。

【问题讨论】:

【参考方案1】:

如果我正确理解了这个问题,您只需要一个 LAG() 和递归 CTE 中分隔符的位置:

表:

CREATE TABLE ManagerDetails (id int, data varchar(1000))
INSERT INTO ManagerDetails (id, data)
VALUES 
   (1, 'imp/imp2/imp3/imp4'),
   (2, 'notimp1/notimp2/notimp3/notimp4')

声明:

DECLARE @separator varchar(1) = '/';
WITH rCTE AS(
    SELECT
       d.id,
       1 as [level] ,
       d.data,
       CAST(1 AS int) AS index1,
       CHARINDEX(@separator, CONCAT(d.data, @separator)) AS index2
    FROM ManagerDetails d   
    UNION ALL
    SELECT
       r.id,
       r.[level] + 1,
       r.data,
       CAST(r.index2 + LEN(@separator) AS int),
       CHARINDEX(@separator, CONCAT(r.data, @separator), r.index2 + 1)
    FROM rCTE r
    WHERE CHARINDEX(@separator, CONCAT(r.data, @separator), r.index2 + 1) > 0
)
SELECT
   id AS Id,
   SUBSTRING(CONCAT(data, @separator), 1, index2 - 1) AS [Value],
   LAG(SUBSTRING(CONCAT(data, @separator), index1, index2 - index1)) OVER (PARTITION BY id ORDER BY level DESC) AS [Manager],
   SUBSTRING(CONCAT(data, @separator), index1, index2 - index1) AS [Employee]
FROM rCTE
ORDER BY id, level DESC
OPTION (MAXRECURSION 0)

结果:

Id Value                           Manager Employee
---------------------------------------------------
1  imp/imp2/imp3/imp4                      imp4
1  imp/imp2/imp3                   imp4    imp3
1  imp/imp2                        imp3    imp2
1  imp                             imp2    imp
2  notimp1/notimp2/notimp3/notimp4         notimp4
2  notimp1/notimp2/notimp3         notimp4 notimp3
2  notimp1/notimp2                 notimp3 notimp2
2  notimp1                         notimp2 notimp1

【讨论】:

但我的表中没有 id 列 @SivamohanReddy,然后在PARTITION BY 中使用data。或其他具有唯一值的列。

以上是关于CTE 递归语句,带自连接,不带 id的主要内容,如果未能解决你的问题,请参考以下文章

使用MySQL 8的递归CTE遍历树

使用MySQL 8的递归CTE遍历树

锚和递归查询“CTE”列“ColumnName”中的递归部分之间的类型不匹配

递归 CTE 性能不佳

在CTE中使用最大递归来生成CTE,而不是仅在最终的SELECT语句中生成CTE

SQL With (递归CTE查询)