从有序表创建层次结构

时间:2019-08-30 13:16:19

标签: sql-server tsql

我有一个表,其中一列具有父子关系。

我可以使用在加载文件时添加的行号来对表进行正确排序。 我想使用排序顺序从列中获取完整的层次结构

样本数据

RowNumber   Type    Area           Name
1           1       Europe         Bob
2           2       Scotland       Bill
3           3       Edinburgh      Dave
4           2       England        Sharron
5           3       London         Tessa
6           2       Spain          Steve
7           2       Portugal       Carie
8           1       Asia           Helen
9           2       Thailand       John
1           2       Japan          Frank
11          3       Tokyo          Kate
12          3       Osaka          Brian
13          1       North America  Joe

我想说一下排除1级=亚洲的行。 很高兴使用临时表或其他任何东西来使它正常工作!

帮助!

2 个答案:

答案 0 :(得分:0)

我在这里猜测,但看起来您正在寻找上级,其值低type 1。这不是传统的分层数据的存储方式,因此我们需要对其进行修复。

首先提供一些消耗品样本数据:

CREATE TABLE dbo.SampleData (RowNumber int,
                             [Type] int,
                             Area varchar(30),
                             [name] varchar(30));
GO

INSERT INTO dbo.SampleData (RowNumber,
                            [Type],
                            Area,
                            [name])
VALUES(1,1,'Europe','Bob'),
      (2,2,'Scotland','Bill'),
      (3,3,'Edinburgh','Dave'),
      (4,2,'England','Sharron'),
      (5,3,'London','Tessa'),
      (6,2,'Spain','Steve'),
      (7,2,'Portugal','Carie'),
      (8,1,'Asia','Helen'),
      (9,2,'Thailand','John'),
      (10,2,'Japan','Frank'),
      (11,3,'Tokyo','Kate'),
      (12,3,'Osaka','Brian'),
      (13,1,'North America','Joe');
GO

现在,我们需要为父母的ID(行号)添加一个新列:

ALTER TABLE dbo.SampleData ADD ParentID int;

然后我们需要填充该列:

UPDATE SD
SET ParentID = P.RowNumber
FROM dbo.SampleData SD
     CROSS APPLY (SELECT TOP 1 ca.RowNumber
                  FROM dbo.SampleData ca
                  WHERE ca.[Type] = SD.[Type] - 1 
                    AND ca.RowNumber < SD.RowNumber
                  ORDER BY ca.RowNumber DESC) P;

现在我们可以实现您想要做的事情,例如使用rCTE(递归公用表表达式)获取与'Asia'不相关的所有行:

WITH rCTE AS(
    SELECT RowNumber,
           [Type],
           Area,
           [name]
    FROM dbo.SampleData
    WHERE [Type] = 1
      AND Area != 'Asia'
    UNION ALL
    SELECT SD.RowNumber,
           SD.Type,
           SD.Area,
           SD.name
    FROM rCTE r
         JOIN dbo.SampleData SD ON r.RowNumber = SD.ParentID)
SELECT r.RowNumber,
       r.[Type],
       r.Area,
       r.[name]
FROM rCTE r;

答案 1 :(得分:0)

如果您拥有已知或最大数量的关卡

示例

Select *
      ,ID  = RowNumber
      ,Pt  = choose( [Type]-1
                   ,max(case when [Type]=1 then RowNumber end) over (Order By RowNumber) 
                   ,max(case when [Type]=2 then RowNumber end) over (Order By RowNumber) 
                   ,max(case when [Type]=3 then RowNumber end) over (Order By RowNumber) 
                   ,max(case when [Type]=4 then RowNumber end) over (Order By RowNumber) 
                   ,max(case when [Type]=5 then RowNumber end) over (Order By RowNumber) 
                   )
 From YourTable A

返回

enter image description here