SQL Server:将行转换为列

时间:2016-09-21 22:12:47

标签: sql sql-server sql-server-2012

我正在尝试制作以下结构

ROW | GROUP | ORDER | COL_NAME  | VALUE
---------------------------------------------
1   | 10    | 10    | FIRST_COL | Value1
2   | 10    | 10    | FIRST_COL | Value2
3   | 10    | 10    | FIRST_COL | Value3
4   | 10    | 20    | SECOND_COL| Val1
5   | 10    | 20    | SECOND_COL| Val2
6   | 20    | 10    | THIRD_COL | Opt3
...

FIRST_COL   | SECOND_COL    | THIRD_COL
-----------------------------------------------------
Value1      | Val1          | Opt3
Value2      | Val2          |
Value3      |               |

我现在有什么:

declare @cols varchar(max),
        @query varchar(max)
select @cols = stuff((select ',' + quotename([COL_NAME])
                    from mt
                    group by [COL_NAME]
                    for xml path(''), type).value('.', 'varchar(max)'), 1, 1, '');


set @query = 'select ' + @cols + ' from (
    select [COL_NAME], [VALUE]
    from mt
) x
pivot (
    min([VALUE])
    for [COL_NAME] in (' + @cols + ')
) p
';
execute(@query);

当前代码仅显示最小值(因为它设置为min([VALUES])),因此只显示Value1,Val1和Opt3,但我的问题是,如何修改代码以便我得到适当的表/视图?

谢谢!

4 个答案:

答案 0 :(得分:2)

这样的东西?

Declare @YourTable table ([ROW] int,[GROUP] int,[ORDER] int,[COL_NAME] varchar(50),[VALUE] varchar(50))
Insert Into @YourTable Values
(1,10,10,'FIRST_COL' ,'Value1'),
(2,10,10,'FIRST_COL' ,'Value2'),
(3,10,10,'FIRST_COL' ,'Value3'),
(4,10,20,'SECOND_COL','Val1'),
(5,10,20,'SECOND_COL','Val2'),
(6,20,10,'THIRD_COL' ,'Opt3')


;with cteBase as (
    Select *
          ,RowNr = Row_Number() over (Partition By [COL_NAME] Order by [ROW])
     From @YourTable
)
Select First_Col  = max(case when [COL_NAME]='FIRST_COL'  then Value else '' end)
      ,Second_Col = max(case when [COL_NAME]='SECOND_COL' then Value else '' end)
      ,Third_Col = max(case when [COL_NAME]='THIRD_COL' then Value else '' end)
 From  cteBase
 Group By RowNr

返回

First_Col   Second_Col  Third_Col
Value1      Val1        Opt3
Value2      Val2    
Value3      

答案 1 :(得分:2)

试试这样:

DECLARE @tbl TABLE([ROW] INT,[GROUP] INT,[ORDER] INT,[COL_NAME] VARCHAR(100),VALUE VARCHAR(100));
INSERT INTO @tbl VALUES
 (1,10,10,'FIRST_COL','Value1')
,(2,10,10,'FIRST_COL','Value2')
,(3,10,10,'FIRST_COL','Value3')
,(4,10,20,'SECOND_COL','Val1')
,(5,10,20,'SECOND_COL','Val2')
,(6,20,10,'THIRD_COL','Opt3');

WITH Sorted AS
(
    SELECT tbl.*
          ,ROW_NUMBER() OVER(PARTITION BY tbl.[COL_NAME] ORDER BY tbl.[ROW]) AS SortInx
    FROM @tbl AS tbl
)
SELECT MAX(CASE WHEN Sorted.[COL_NAME]='FIRST_COL' THEN Sorted.[VALUE] END) AS FIRST_COL 
      ,MAX(CASE WHEN Sorted.[COL_NAME]='SECOND_COL' THEN Sorted.[VALUE] END) AS SECOND_COL 
      ,MAX(CASE WHEN Sorted.[COL_NAME]='THIRD_COL' THEN Sorted.[VALUE] END) AS THIRD_COL 
FROM Sorted
GROUP BY SortInx

答案 2 :(得分:2)

我相信你需要这个:

set @query = 'select ' + @cols + ' from (
    select [COL_NAME], [VALUE], ROW_NUMBER() OVER (PARTITION BY [COL_NAME] ORDER BY (SELECT NULL)) as seqnum
    from mt
) x
pivot (
    min([VALUE])
    for [COL_NAME] in (' + @cols + ')
) p
';

pivot使用子查询中的所有列。您只需要用一个来区分具有相同列名的行。

答案 3 :(得分:0)

正如他所说,您需要使用RowNumber()填充COL_NAME上的Row列,这样您的数据就会如下所示。

ROW | GROUP | ORDER | COL_NAME  | VALUE
---------------------------------------------
1   | 10    | 10    | FIRST_COL | Value1
2   | 10    | 10    | FIRST_COL | Value2
3   | 10    | 10    | FIRST_COL | Value3
1   | 10    | 20    | SECOND_COL| Val1
2   | 10    | 20    | SECOND_COL| Val2
1   | 20    | 10    | THIRD_COL | Opt3
...

然后,只需在SQL

中包含该列
set @query = 'select [Row], ' + @cols + ' from (
    select [Row],[COL_NAME], [VALUE]
    from mt
) x
pivot (
    min([VALUE])
    for [COL_NAME] in (' + @cols + ')
) p
';
execute(@query);

然后,你有

ROW FIRST_COL   SECOND_COL  THIRD_COL
1   Value1          Val1            Opt3
2   Value2          Val2            NULL
3   Value3          NULL            NULL