如何仅根据行号将单列 table 变成多列?

How do I turn a single column table into multiple columns based solely on row number?

因此,我将此数据存在于单个列中。奇数行是ID,偶数行是城市。有没有办法将其分成两列?

    DECLARE @Data TABLE (
          DataRow       NVARCHAR(50)
          )

    INSERT INTO @Data VALUES 

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

现在我正在使用以下代码,但似乎应该有更有效的方法来使用枢轴 table。

    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

结果:

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

这将适用于您的小 table 变量,但是,如果来自 table,则没有固有的行顺序,结果可以不是 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

Returns

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

另一种选择,以确保正确的顺序是将数据解析为带有 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

Returns

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