作为 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 列中。
也许是这样的:
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
输出:
锚 | 父锚 | SEC | BRC | 奥布 |
---|---|---|---|---|
HCC_AK4 | BRC_BOZ | 空 | 博兹 | 李光耀 |
HCC_BH1 | OBU_BGH | 空 | 空 | BGH |
HCC_Z5 | SEC_LNG | 液化天然气 | 林 | LNM |
HCC_AS1 | SEC_SMI | 星美 | 并且 | 并且 |