2017-06-06 208 views
2

所以,我有这个数据存在于一个列中。奇数行是ID,偶数行是城市。有没有办法将它分成两列?如何仅基于行号将单列表转换为多列?

DECLARE @Data TABLE (
      DataRow  NVARCHAR(50) 
     ) 

    INSERT INTO @Data VALUES 

      ('1'    ) 
     , ('Albuquerque' ) 
     , ('2'    ) 
     , ('Boston'  ) 
     , ('3'    ) 
     , ('Chicago'  ) 
     , ('4'    ) 
     , ('Dayton'  ) 
     , ('5'    ) 
     , ('Eumenclaw'  ) 
     , ('6'    ) 
     , ('Fresno'  ) 

现在,我使用下面的代码,但它好像应该是使用数据透视表更有效的方式。

DECLARE @DataID TABLE (
      ID   INT IDENTITY 
      , DataRow  NVARCHAR(50) 
     ) 

    INSERT INTO @DataID 
     SELECT * FROM @Data 

    DECLARE @CityData TABLE (
      ID   INT 
     , City   NVARCHAR(100) 
     ) 

    DECLARE @Counter  INT = 0 
      , @ID   INT 
      , @City   NVARCHAR(50) 

    WHILE @Counter < (SELECT MAX(ID)/2 FROM @DataID WHERE ID%2 = 0) 
     BEGIN 
      SET @Counter += 1 
      SET @ID = (SELECT CAST(DataRow AS INT) FROM @DataID WHERE ID = @Counter * 2 - 1) 
      SET @City = (SELECT DataRow FROM @DataID WHERE ID = @Counter * 2) 
      INSERT INTO @CityData 
       SELECT @ID, @City 


     END 

    SELECT * FROM @CityData 

结果:

enter image description here

哦,对不住那些你从华盛顿的拼写错误。希望不是新墨西哥州。

回答

4

这将适用于您的小表变量,但是,如果来自表,没有固有的行顺序,并且结果不能是gtd。

Select ID = max(case when DataRow Like  '[0-9]%' then DataRow end) 
     ,City = max(case when DataRow Not Like '[0-9]%' then DataRow end) 
From (
     Select * 
       ,Grp = (Row_Number() over (Order by (Select NULL)) -1)/2 
     From @Data 
    ) A 
Group By Grp 

返回

ID City 
1 Albuquerque 
2 Boston 
3 Chicago 
4 Dayton 
5 Eumenclaw 
6 Fresno 
+0

哇。我在这里一直受到思想和专业知识的吹捧。这真是不可思议。当然,我修改了它(不能在这里发布真实的数据,所以我使用轶事)。我拥有的数据是完全可预测的,所以我可以在ID上使用MOD功能。但是,你给了我我需要的东西,谢谢。辉煌。 – DaveX

+0

@DaveX快乐它帮助:) –

+0

@DaveX我也喜欢SO。我每天都会学到新的东西。这是有趣的部分 –

0

又一选项,以确保正确的顺序是具有CRLF定界符

考虑以下解析的数据作为串:

Declare @Delimiter varchar(25) = char(13)+char(10) 
Declare @String varchar(max) = ' 
1 
Albuquerque 
2 
Boston 
3 
Chicago 
4 
Dayton 
5 
Eumenclaw 
6 
Fresno 
' 

Select ID = max(case when RetSeq % 2 = 1 then RetVal end) 
     ,City = max(case when RetSeq % 2 = 0 then RetVal end) 
From (
     Select *,Grp = (RetSeq-1)/2 
     From (
       Select RetSeq = Row_Number() over (Order By (Select null)) 
         ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
       From (Select x = Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
       Cross Apply x.nodes('x') AS B(i) 
       Where LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) is not null 
      ) A1 
    ) A 
Group By Grp 

返回

ID City 
1 Albuquerque 
2 Boston 
3 Chicago 
4 Dayton 
5 Eumenclaw 
6 Fresno