如何仅根据行号将单个列表转换为多个列?

时间:2017-06-06 16:45:22

标签: sql-server tsql ssms-2012

所以,我将这些数据存在于一个列中。奇数行是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

哦,并向华盛顿的那些拼写错误的人道歉。希望不是新墨西哥州。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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