在递归联合 cte 的开头保持恒定的标识值

问题描述 投票:0回答:1

作为 Microsoft SQL Server 上的 T-SQL 项目的一部分,我使用递归联合 CTE 通过一些分层数据跟踪一系列子父关系,将每个单独的元素拉入一行,然后将其转换为单排。

作为示例,我的递归联合 CTE 会将四个 HCC 值的以下行从 A(源表)转换为 B(递归联合表)。 C 将是枢轴后期望的结果。

A

MEMBER_NAME PARENT_NAME
HCC_AS1 SEC_SMI
SEC_SMI BRC_AND
BRC_AND OBU_AND
HCC_AK4 BRC_BOZ
BRC_BOZ OBU_LKY
HCC_BH1 OBU_BGH
HCC_Z5 SEC_LNG
SEC_LNG BRC_LYN
BRC_LYN OBU_LNM

B

MEMBER_NAME PARENT_NAME 层次结构 价值
HCC_AS1 SEC_SMI SEC 星美
HCC_AS1 SEC_SMI BRC 并且
HCC_AS1 SEC_SMI 奥布 并且
HCC_AK4 BRC_BOZ BRC 博兹
HCC_AK4 BRC_BOZ 奥布 李光耀
HCC_BH1 OBU_BGH 奥布 BGH
HCC_Z5 SEC_LNG SEC 液化天然气
HCC_Z5 SEC_LNG BRC
HCC_Z5 SEC_LNG 奥布 LNM

C

MEMBER_NAME PARENT_NAME SEC BRC 奥布
HCC_AS1 SEC_SMI 星美 并且 并且
HCC_AK4 BRC_BOZ 博兹 李光耀
HCC_BH1 OBU_BGH BGH
HCC_Z5 SEC_LNG 液化天然气 LNM

我唯一遇到的麻烦是为整个递归 CTE 保留原始的

MEMBER_NAME
PARENT_NAME
,这是项目的要求。我将它包裹在游标中并插入到临时表中,这样我就有了一些东西供他们查看,但他们想将其更改为视图,所以我不相信我当前的设计会持续下去。我不太精通递归查询。有没有我缺少的解决方案可以用来将其变成视图?

DECLARE @member varchar(80)
DECLARE @parent varchar(80)

CREATE TABLE #Temp
(
    MEMBER_NAME varchar(80),
    PARENT_NAME varchar(80),
    Hierarchy varchar(80),
    [Value] varchar(80)
);
 
DECLARE member_cursor CURSOR FOR 
    SELECT
        [MEMBER_NAME], [PARENT_NAME]
    FROM 
        [CACHED_OUTLINE_MEMBERS]
    WHERE 
        DIMENSION_NAME = 'Delivery_Center'
        AND LEFT(MEMBER_NAME, 3) = 'HCC'
        AND LEFT(PARENT_NAME, 3) IN ('SEC', 'OBU', 'BRC')
 
OPEN member_cursor
 
FETCH NEXT FROM member_cursor INTO @member, @parent
 
WHILE @@FETCH_STATUS = 0
BEGIN
    WITH Parent AS
    (
        SELECT
            LEFT(PARENT_NAME, CHARINDEX('_', Parent_name) -1) AS Hierarchy,
            RIGHT(Parent_name, LEN(parent_name) - CHARINDEX('_', Parent_name)) AS [Value]
        FROM 
            [CACHED_OUTLINE_MEMBERS]
        WHERE
            MEMBER_NAME = @member
 
        UNION ALL
 
        SELECT
            LEFT(C.PARENT_NAME, CHARINDEX('_', C.Parent_name) -1) AS Hierarchy, 
            RIGHT(C.Parent_name, LEN(C.parent_name) - CHARINDEX('_', C.Parent_name)) AS [Value]
        FROM 
            [CACHED_OUTLINE_MEMBERS] C
        INNER JOIN 
            Parent ON C.member_name = parent.parent_name
        WHERE
            LEFT(C.PARENT_NAME, CHARINDEX('_', C.Parent_name) -1) IN ('SEC', 'OBU', 'BRC')
    )
    INSERT INTO #Temp
        SELECT 
            @member AS MEMBER_NAME, @parent AS PARENT_NAME, Hierarchy, [Value]  
        FROM
            Parent
 
    FETCH NEXT FROM member_cursor INTO @member, @parent 
END
 
CLOSE member_cursor
DEALLOCATE member_cursor
 
SELECT * FROM #Temp

我尝试了光标,但那时我认为这可能只是一个每天构建一次的表。但他们希望它成为一个视图,所以我必须想出一个不需要光标的设计。

在使用递归 CTE 之前,我尝试只做一个自连接表,但数据的子父关系不一致。某些 HCC 值没有 SEC 或 BRC 或两者,因此仅执行三个自连接有时会将 OBU 放置在 SEC 或 BRC 列中。

sql-server t-sql hierarchical-data recursive-cte
1个回答
0
投票

也许是这样的:

WITH data AS (
SELECT  *
FROM    (
    VALUES  (N'HCC_AS1', N'SEC_SMI')
    ,   (N'SEC_SMI', N'BRC_AND')
    ,   (N'BRC_AND', N'OBU_AND')
    ,   (N'HCC_AK4', N'BRC_BOZ')
    ,   (N'BRC_BOZ', N'OBU_LKY')
    ,   (N'HCC_BH1', N'OBU_BGH')
    ,   (N'HCC_Z5', N'SEC_LNG')
    ,   (N'SEC_LNG', N'BRC_LYN')
    ,   (N'BRC_LYN', N'OBU_LNM')
) t (MEMBER_NAME,PARENT_NAME)
)
, cte AS (
    SELECT  MEMBER_NAME AS anchor, PARENT_NAME AS parent_anchor, PARENT_NAME AS parent, LEFT(PARENT_NAME, 3) AS hierarchy, RIGHT(PARENT_NAME, 3) AS Value
    FROM    data d
    WHERE   NOT EXISTS(
            SELECT  1
            FROM    data d2
            WHERE   d2.parent_name = d.member_name
        )
    UNION ALL
    SELECT  anchor, parent_anchor, d.parent_name, LEFT(PARENT_NAME, 3) AS hierarchy, RIGHT(PARENT_NAME, 3) AS Value
    FROM    cte c
    INNER JOIN data d
        ON  d.MEMBER_NAME = c.parent
)
SELECT  *
FROM    (
    SELECT  anchor, parent_anchor, hierarchy, value
    FROM    cte
    ) x
PIVOT (max(value) FOR hierarchy IN (SEC, BRC,OBU)) y
  1. 我创建了两列,它们保留为锚点,并且从顶部开始不会改变
  2. 然后可以对其余列执行标准递归 CTE 操作。
  3. 最后,对于数据透视表,我删除了不必要的父列并从其余字段创建数据透视表。

输出:

父锚 SEC BRC 奥布
HCC_AK4 BRC_BOZ 博兹 李光耀
HCC_BH1 OBU_BGH BGH
HCC_Z5 SEC_LNG 液化天然气 LNM
HCC_AS1 SEC_SMI 星美 并且 并且
© www.soinside.com 2019 - 2024. All rights reserved.