将行值拆分为Columns-TSQL

时间:2018-04-11 10:23:46

标签: sql sql-server tsql pivot

我已搜索SQL Server : rows into columns将行值拆分为列,但这对我没有帮助

我有样本数据

Col1
0183125031218
13020690831
79100146868
0183225031138
13010690834
79100145497

预期产出:

Col1             Col2             Col3 
0183125031128    13020690831      79100146868
0183225031138    13010690834      79100145497

我的尝试:

我尝试使用Row_number功能,但未获得所需的输出。因为我需要left(col,2) = 01到第一列和left(col,2)=13到第二列的条件分割。基于第一列,可以分配行号。任何行数据都没有固定长度

Apreciate任何帮助或建议

4 个答案:

答案 0 :(得分:2)

尝试以下查询

-- test data
CREATE TABLE TestData(Col1 varchar(20))

INSERT TestData(Col1)VALUES
('0183125031218'),
('13020690831'),
('79100146868'),
('0183225031138'),
('1301069083'),
('79100145497')

-- query
SELECT
  COALESCE(q1.N,q2.N,q3.N) RowNum,
  q1.Col1,
  q2.Col1 Col2,
  q3.Col1 Col3
FROM
  (
    SELECT ROW_NUMBER()OVER(ORDER BY Col1) N,Col1
    FROM TestData
    WHERE Col1 LIKE '01%'
  ) q1
FULL JOIN
  (
    SELECT ROW_NUMBER()OVER(ORDER BY Col1) N,Col1
    FROM TestData
    WHERE Col1 LIKE '13%'
  ) q2
ON q2.N=q1.N
FULL JOIN
  (
    SELECT ROW_NUMBER()OVER(ORDER BY Col1) N,Col1
    FROM TestData
    WHERE Col1 LIKE '79%'
  ) q3
ON q3.N=COALESCE(q1.N,q2.N)

带有PIVOT

的变体
SELECT *
FROM
  (
    SELECT
      LEFT(Col1,2) RowType,
      ROW_NUMBER()OVER(PARTITION BY LEFT(Col1,2) ORDER BY Col1) N,
      Col1
    FROM TestData
  ) q PIVOT(MAX(Col1) FOR RowType IN([01],[13],[79])) p

答案 1 :(得分:2)

如何使用CTE分配行号和分组?

CREATE TABLE #Sample (Col1 varchar(50));
GO
INSERT INTO #Sample
VALUES ('0183125031218'),
       ('13020690831'),
       ('79100146868'),
       ('0183225031138'),
       ('1301069083'),
       ('79100145497');
GO

SELECT *
FROM #SAmple;

WITH Grp AS(
    SELECT Col1,
           LEFT(Col1,2) AS Grp,
           ROW_NUMBER() OVER (PARTITION BY LEFT(Col1,2) ORDER BY Col1) AS RN
    FROM #Sample)
SELECT G1.Col1 AS Col1,
       G2.Col1 AS Col2,
       G3.Col1 AS Col3
FROM Grp G1
     JOIN Grp G2 ON G1.RN = G2.RN
                AND G2.Grp = '13'
     JOIN Grp G3 ON G1.RN = G3.RN
                AND G3.Grp = '79'
WHERE G1.Grp = '01';
GO

DROP TABLE #Sample;

这使得查询比在leran2002的答案中使用UNION更简洁/更短。

答案 2 :(得分:1)

试试这个。背后的想法是根据给定的条件将表拆分为三列,然后根据row_number()将它们连接回来,没有任何排序,因为你告诉特定记录之间没有关系。

declare @table table(col1 varchar(100))
insert into @table values
('0183125031218'),
('13020690831'),
('79100146868'),
('0183225031138'),
('1301069083'),
('79100145497')

select [col1],[col2],[col3] from
--IMPORTANT: here should go the query, that will have the most records!!!
(select col1 [col1], ROW_NUMBER() over (order by (select null)) [rn1] from @table where LEFT(col1, 2) = '01') [c1]
left join
(select col1 [col2], ROW_NUMBER() over (order by (select null)) [rn2] from @table where LEFT(col1, 2) = '13') [c2]
on [rn1]=[rn2] left join
(select col1 [col3], ROW_NUMBER() over (order by (select null)) [rn3] from @table where not LEFT(col1, 2) in ('01','13')) [c3]
on [rn1]=[rn3]

答案 3 :(得分:0)

与Larnu(+1)相同 我只是想测试一下

declare @T TABLE (col varchar(50));
INSERT INTO @T
VALUES ('0183125031218'),
       ('13020690831'),
       ('79100146868'),
       ('0183225031138'),
       ('13010690834'),
       ('79100145497');
SELECT *
FROM @T;

WITH cte AS
( SELECT col, LEFT(col,2) AS grp, 
         ROW_NUMBER() OVER (PARTITION BY LEFT(col,2) ORDER BY col) AS rn
    FROM @T  
    where LEFT(col,2) in ('01', '13', '79')
)
SELECT G1.col AS Col1,
       G2.col AS Col2,
       G3.col AS Col3
FROM cte G1
JOIN cte G2 ON G1.RN = G2.RN
           and G1.Grp = '01'
           AND G2.Grp = '13'
JOIN cte G3 ON G1.RN = G3.RN
           AND G3.Grp = '79'
order by G1.col, G2.col, G3.col;