将具有多个父/子级别的层次结构的数据的列拆分为多个列(递归CTE层次结构)

时间:2019-03-25 14:50:23

标签: sql-server

我想在SQL查询中解决以下问题。我查找了许多子级/父级以及层次结构主题的多个级别,尽管我走得很远,但还是无法找到最佳解决方案。

我有一个表,该表的一列内有一个层次结构,我想透视此层次结构。我走得很远,但由于最终结果中有不必要的双行,并且最终结果中层次结构的层次混合在一起,因此我陷入了困境。首先,我将解释有关当前数据集的更多信息,然后,我将解释如何得出当前结果。

我有一个名为PMEGROUND的表。该表包含单位,邻里和城市的数据。一个单位,邻里或城市始终具有唯一的对象和地面对象。

在GROUNDID内,有公寓,街区和城市,都在同一列中。但是,它们可以具有指向GROUNDID父级的MAINGROUNDID。因此,公寓属于社区,城市属于社区;但现在公寓也属于城市。这是我当前数据集的一小部分:

 CREATE TABLE PMEGROUND (
 OBJECTID nvarchar(20),
 GROUNDID nvarchar(20),
 MAINGROUNDID nvarchar(20));

 INSERT INTO PMEGROUND (ObjectId, GroundId, MaingroundId)
 VALUES
  ('2','1',''), --City
  ('3','101','1'), -- Neighborhood
  ('4','10101','101'), -- Flat
  ('5','10102','101'),
  ('6','10103','101'),
  ('7','10104','101'),
  ('8','10105','101'),
  ('10','102','1'),
  ('11','10201','102'),
  ('12','10202','102'),
  ('13','10203','102'),
  ('14','10204','102'),
  ('16','103','1'),
  ('17','10301','103'),
  ('18','10302','103');

重要的是,公寓并非只有5个字符,而邻里只有3个字符。

我已经迷惑了一段时间,到目前为止,我确实陷入了下面的代码。它确实创建了一个层次结构,但是: 1)混合级别; 2)它也会以某种方式保留原始表的选择,因此看起来它已将“扩展列层次结构”添加到原始表内容中。这些行是双行,而每个唯一的ObjectId应该有1行。我尝试使用Union而不是Union All,但是保留了双行。

;with cteP as (
      Select GROUNDID
            ,OBJECTID
            ,MAINGROUNDID 
            ,PathID = cast(GROUNDID as varchar(max))
      From   PMEGROUND
      Where  REPLACE(ltrim(rtrim(MAINGROUNDID)),' ',NULL)  is Null
      Union  All
      Select GROUNDID      = r.GROUNDID
            ,OBJECTID       = r.OBJECTID
            ,MAINGROUNDID  = r.MAINGROUNDID 
            ,PathID = p.PathID+concat(',',cast(r.GROUNDID as varchar(max)))
      From   PMEGROUND r
      Join   cteP p on r.MAINGROUNDID  = p.GROUNDID)
Select A.GROUNDID
       ,OBJECTID
      ,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

现在,我希望不再在2列中包含此层次结构,但我希望将其扩展到多个列中,最终结果应该看起来像这样:

 CREATE TABLE PMEGROUNDFIX (
 OBJECTID nvarchar(20),
 Lvl1 nvarchar(20),
 Lvl2 nvarchar(20),
 Lvl3 nvarchar(20),
 Lvl4 nvarchar(20));

 INSERT INTO PMEGROUNDFIX (ObjectId, Lvl1, Lvl2, Lvl3, Lvl4)
 VALUES
  ('2','','','1',''), /*City*/
  ('3','','101','1',''), /*Neighborhood*/
  ('4','10101','101','1',''), /*Flat*/
  ('5','10102','101','1',''),
  ('6','10103','101','1',''),
  ('7','10104','101','1',''),
  ('8','10105','101','1',''),
  ('10','','102','1',''),
  ('11','10201','102','1',''),
  ('12','10202','102','1',''),
  ('13','10203','102','1',''),
  ('14','10204','102','1',''),
  ('16','','103','1',''),
  ('17','10301','103','1',''),
  ('18','10302','103','1','');

但是它的外观如下:

  CREATE TABLE PMEGROUNDWRONG (
  OBJECTID nvarchar(20),
  Lvl1 nvarchar(20),
  Lvl2 nvarchar(20),
  Lvl3 nvarchar(20),
  Lvl4 nvarchar(20));

  INSERT INTO PMEGROUNDWRONG (ObjectId, Lvl1, Lvl2, Lvl3, Lvl4)
  VALUES
  ('2','1','','',''),
  ('3','101','1','',''),
  ('3','101','','',''),
  ('4','10101','101','1',''),
  ('4','10101','','',''),
  ('5','10102','101','1',''),
  ('5','10102','','',''),
  ('6','10103','101','1',''),
  ('6','10103','','',''),
  ('7','10104','101','1',''),
  ('7','10104','','',''),
  ('8','10105','101','1',''),
  ('8','10105','','',''),
  ('10','102','1','',''),
  ('10','102','','',''),
  ('11','10201','102','1',''),
  ('11','10201','','',''),
  ('12','10202','102','1',''),
  ('12','10202','','',''),
  ('13','10203','102','1',''),
  ('13','10203','','',''),
  ('14','10204','102','1',''),
  ('14','10204','','',''),
  ('16','103','1','',''),
  ('16','103','','',''),
  ('17','10301','103','1',''),
  ('17','10301','','',''),
  ('18','10302','103','1',''),
  ('18','10302','','','');

因此,您可以看到上面给出的数据集混合了层次结构级别,并且以某种方式具有双行。

有人知道我在这里缺少什么重要的东西吗?

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

1 个答案:

答案 0 :(得分:1)

您的xDim位置在相反的方向,同样,您启动递归CTE的过滤器是错误的,这就是为什么您获取重复项的原因

x = 0
while int(x)>= 0 :
    try :
        x, y = input("Enter a two value: ").split() 
    except ValueError:
        print("You missed one")
    print("This is x : ", x) 
    print("This is y : ", y)