根据以下情况在SQL Server中创建父子关系

时间:2018-11-27 06:18:40

标签: sql sql-server tsql

enter image description here

在此图中, 2018_9UKDT-UKD费用总计 2018_9Q400-UKD间接的父级,而这又是 98064-IT SDS成本98063的父级-ACS收费,98012-UKD-中部。

有人可以让我知道如何使用具有多达10个级别的T-SQL创建父子关系。

创建表格

create table Test
(
    ID INT IDENTITY(1,1),
    NAME VARCHAR (255),
    Level Varchar(25)
);

insert into test (name) values
('     2018_9UKDT - UKD Expense Total'),
('          2018_9Q400 - UKD Indirects'),
('               98064 - IT SDS Costs'),
('               98063 - ACS in charges'),
('               98012 - UKD - Central'),
('          2018_9Q300 - UKD Non Opex Total');

,输出将在下面的附件屏幕快照中。 基本上是从最低级别到升序。

enter image description here

1 个答案:

答案 0 :(得分:1)

由于您知道最大级别为10,因此可以使用几个常见的表表达式和条件聚合:

With CTE1 AS 
(
SELECT  Id, 
        name, 
        DENSE_RANK() OVER(ORDER BY LEN(name) - LEN(LTRIM(name)) DESC) As Level
FROM Test
), CTE2 AS
(
SELECT  Id, 
        Name, 
        Level,
        ISNULL((SELECT MIN(ID)
         FROM CTE1 As t1
         WHERE T1.Level > T0.Level 
         ), Id) As ParentId
FROM CTE1 As T0
)

SELECT MAX(CASE WHEN Level = 1 THEN Trimmed END) As Level1
      ,MAX(CASE WHEN Level = 2 THEN Trimmed END) As Level2
      ,MAX(CASE WHEN Level = 3 THEN Trimmed END) As Level3
      ,MAX(CASE WHEN Level = 4 THEN Trimmed END) As Level4
      -- more of the same
FROM CTE2
CROSS APPLY
(SELECT LTRIM(RTRIM(Name)) As Trimmed) As DRY
GROUP BY ParentId

结果(针对问题上张贴的示例数据):

    Level1                      Level2                          Level3                              Level4
    98064 - IT SDS Costs        2018_9Q400 - UKD Indirects      2018_9UKDT - UKD Expense Total      NULL

请注意,对于多个根节点,将很难知道根节点在哪里(基本上,您可以将Level1Level2 ...设置为null,至少将其中一个设置为null节点有更多的孩子。

因此,您可能应该在最左侧的列中具有根节点。为此,请将dense_rank的顺序从DESC更改为ASK,将第二个cte中子查询的条件从WHERE T1.Level > T0.Level更改为WHERE T1.Level < T0.Level。 / p>