将2个子级/父级列拆分(去规范化)为多个列(基于父级数)

时间:2019-03-07 13:17:55

标签: sql-server

我在2列中有我的ChildID和ParentID,但是我想将这些列拆分为几列,但所有列仍指向其父级,并且在适用时也指向该父级的父级。

可能是数据集只有3个级别,如下所示,但在某些情况下可能也有4个级别,因此变得更加困难,因为它必须具有一定的动态性。

下面是我当前的数据集,一个子/父表:

            ID, PARID,
            1,  
            1,  
            10,     1
            11,     1
            20,     2
            21,     2
            100,    10
            101,    10
            110,    11
            111,    11
            200,    20
            201,    20
            210,    21
            211,    21

以下是我想要的样子:

            LVL1    LVL2    LVL3
            1,
            1,
            1,      10,
            1,      11,
            2,      20,
            2,      21,
            1,      10,     100,
            1,      10,     101,
            1,      11,     110,
            1,      11,     111,
            2,      20,     200,
            2,      20,     201,
            2,      21,     210,
            2,      21,     211,

ID名称不一定是我希望如何调用它们,但这仅是示例。另外,“孩子”并不总是包含父母的ID。

我无法在线找到正确的信息,最终只能找到如何创建子表/父表的方法,而不是尝试相反的方法。

非常感谢您的帮助。

编辑: 由于到目前为止的反应,我显示了我的实际数据,尽管实际上它有12000行,并且如您所见,它具有自动生成的唯一键,这可能是必须知道的:

                                OBJECTID,GROUNDID,MAINGROUNDID, 
                                1,      024,    
                                2,      025,    
                                3,      026,    
                                4,      02610,  026,
                                5,      02620,  026,
                                6,      02630,  026,
                                7,      02640,  026,
                                8,      02650,  026,
                                9,      027,    
                                10,     028,    
                                11,     029,    
                                12,     030,    
                                13,     03010,  030,
                                14,     03020,  030,
                                15,     03030,  030,
                                16,     03040,  030,
                                17,     030401, 03040,

编辑,到目前为止,结果是双行:

                                    GROUNDID,Lvl1,Lvl2,Lvl3,Lvl4  
                                    006     006     NULL    NULL    NULL
                                    007     007     NULL    NULL    NULL
                                    008     008     NULL    NULL    NULL
                                    009     009     NULL    NULL    NULL
                                    010     010     NULL    NULL    NULL
                                    011     011     NULL    NULL    NULL
                                    014     014     NULL    NULL    NULL
                                    015     015     NULL    NULL    NULL
                                    016     016     NULL    NULL    NULL
                                    017     017     NULL    NULL    NULL
                                    018     018     NULL    NULL    NULL
                                    019     019     NULL    NULL    NULL
                                    020     020     NULL    NULL    NULL
                                    021     021     NULL    NULL    NULL
                                    022     022     NULL    NULL    NULL
                                    023     023     NULL    NULL    NULL
                                    024     024     NULL    NULL    NULL
                                    025     025     NULL    NULL    NULL
                                    026     026     NULL    NULL    NULL
                                    02610   026     02610   NULL    NULL
                                    02620   026     02620   NULL    NULL
                                    02630   026     02630   NULL    NULL
                                    02640   026     02640   NULL    NULL
                                    02650   026     02650   NULL    NULL
                                    02610   02610   NULL    NULL    NULL
                                    02620   02620   NULL    NULL    NULL
                                    02630   02630   NULL    NULL    NULL
                                    02640   02640   NULL    NULL    NULL
                                    02650   02650   NULL    NULL    NULL

亲切的问候, 伊戈尔(Igor)

2 个答案:

答案 0 :(得分:1)

这里是使用标准递归CTE来构建层次结构并使用一些XML来解析列的选项

示例

;with cteP as (
      Select ID
            ,PARID 
            ,PathID = cast(ID as varchar(max))
      From   YourTable
      Where  PARID is Null
      Union  All
      Select ID  = r.ID
            ,PARID  = r.PARID 
            ,PathID = p.PathID+concat(',',r.ID)
      From   YourTable r
      Join   cteP p on r.PARID  = p.ID)
Select A.ID
      ,B.*
 From  cteP A
 Cross Apply (
                Select Lvl1 = xDim.value('/x[1]','int')
                      ,Lvl2 = xDim.value('/x[2]','int')
                      ,Lvl3 = xDim.value('/x[3]','int')
                      ,Lvl4 = xDim.value('/x[4]','int')
                From  ( values (cast('<x>' + replace(PathID,',','</x><x>')+'</x>' as xml))) B(xDim)
             ) B
  Order By PathID

返回

enter image description here

  

编辑-更新了真实数据

;with cteP as (
      Select GROUNDID
            ,MAINGROUNDID 
            ,PathID = cast(GROUNDID as varchar(max))
      From   YourTable
      Where  MAINGROUNDID is Null
      Union  All
      Select GROUNDID      = r.GROUNDID
            ,MAINGROUNDID  = r.MAINGROUNDID 
            ,PathID = p.PathID+concat(',',r.GROUNDID)
      From   YourTable r
      Join   cteP p on r.MAINGROUNDID  = p.GROUNDID)
Select A.GROUNDID
      ,B.*
 From  cteP A
 Cross Apply (
                Select Lvl1 = xDim.value('/x[1]','varchar(50)')
                      ,Lvl2 = xDim.value('/x[2]','varchar(50)')
                      ,Lvl3 = xDim.value('/x[3]','varchar(50)')
                      ,Lvl4 = xDim.value('/x[4]','varchar(50)')
                From  ( values (cast('<x>' + replace(PathID,',','</x><x>')+'</x>' as xml))) B(xDim)
             ) B
  Order By PathID

返回

enter image description here

  

编辑2

我假设您的源数据看起来像这样

enter image description here

答案 1 :(得分:0)

对我来说,您的设计是错误的。您有一个Person实体,该实体与其自身具有多对多关系:
-一个人可以有几个父母
-一个人可以是0个或多个孩子的父母。

在关系模型中,关系表表示多对多关系。因此,您应该有2个表:

  • 人员:身份证,姓名,出生日期等...
  • RelationShip:ParentId,ChildId

这将允许您表示任何深度的父子关系。