SQL - 将列转换为包括列名的行

时间:2017-04-18 12:20:05

标签: sql sql-server sql-server-2008 pivot unpivot

我有一张这样的表:

date    subj1   subj2   subj3   subj4
1       20       5      30      7
2       15      14      29      4
3       15      14      29      14

我想按照以下方式安排:

date    1   2   3
subj1   20  15  35
subj2   5   14  14
subj3   30  29  29
subj4   7   4   14

如何使用pivot或unpivot在SQL中实现此目的?

3 个答案:

答案 0 :(得分:1)

使用cross apply()values()一起取消common table expression中的数据,然后使用pivot()将其展开:

with cte as (
  select t.date, v.subject, v.value
  from t
  cross apply (values ('subj1',subj1),('subj2',subj2),('subj3',subj3),('subj4',subj4)) v(subject,value)
)

select subject, [1],[2],[3]
from cte
pivot (max(value) for [date] in ([1],[2],[3])) p

rextester演示:http://rextester.com/QJMRBF98845

返回:

+---------+----+----+----+
| subject | 1  | 2  | 3  |
+---------+----+----+----+
| subj1   | 20 | 15 | 15 |
| subj2   |  5 | 14 | 14 |
| subj3   | 30 | 29 | 29 |
| subj4   |  7 |  4 | 14 |
+---------+----+----+----+

如果您希望subjectdate调用,请在select中将其别名:

with cte as (
  select t.date, v.subject, v.value
  from t
  cross apply (values ('subj1',subj1),('subj2',subj2),('subj3',subj3),('subj4',subj4)) v(subject,value)
)

select subject as date, [1],[2],[3]
from cte
pivot (max(value) for [date] in ([1],[2],[3])) p

rextester演示:http://rextester.com/XQAE51432

返回:

+-------+----+----+----+
| date  | 1  | 2  | 3  |
+-------+----+----+----+
| subj1 | 20 | 15 | 15 |
| subj2 |  5 | 14 | 14 |
| subj3 | 30 | 29 | 29 |
| subj4 |  7 |  4 | 14 |
+-------+----+----+----+

答案 1 :(得分:0)

使用PIVOT

declare @table table (data int ,subj1 int ,subj2 int,subj3 int, subj4 int )

insert into  @table 
select 1      , 20     ,  5     , 30  ,    7
union all select 2      , 15     , 14     , 29  ,    4
union all select 3      , 15     , 14     , 29  ,    14

select 'subj1' as [date],* from (
select data,subj1  from
@table) a
pivot ( sum(subj1) for data in ([1],[2],[3]))p

union all
select 'subj2' as [date],* from (
select data,subj2  from
@table) a
pivot ( sum(subj2) for data in ([1],[2],[3]))p

union all

select 'subj3' as [date],* from (
select data,subj3  from
@table) a
pivot ( sum(subj3) for data in ([1],[2],[3]))p
union all   
select 'subj4' as [date],* from (
select data,subj4  from
@table) a
pivot ( sum(subj4) for data in ([1],[2],[3]))p

<强> RESULT

+-------+----+----+----+
| date  | 1  | 2  | 3  |
+-------+----+----+----+
| subj1 | 20 | 15 | 15 |
| subj2 |  5 | 14 | 14 |
| subj3 | 30 | 29 | 29 |
| subj4 |  7 |  4 | 14 |

答案 2 :(得分:0)

CREATE TABLE #TABLE12
    ([DATE] INT, [SUBJ1] INT, [SUBJ2] INT, [SUBJ3] INT, [SUBJ4] INT)
;

INSERT INTO #TABLE12
    ([DATE], [SUBJ1], [SUBJ2], [SUBJ3], [SUBJ4])
VALUES
    (1, 20, 5, 30, 7),
    (2, 15, 14, 29, 4),
    (3, 15, 14, 29, 14)

 SELECT SUBJECT
    ,MAX([1])[1]
    ,MAX([2])[2]
    ,MAX([3])[3]
FROM(SELECT *
FROM #TABLE12
CROSS APPLY (VALUES ('SUBJ1', SUBJ1),
                    ('SUBJ2', SUBJ2),
                    ('SUBJ3', SUBJ3),
                    ('SUBJ4', SUBJ4)
                    ) 
            CROSSAPPLIED ([SUBJECT], VALUE))A
PIVOT(MAX(VALUE) FOR [DATE] IN (
            [1]
            ,[2]
            ,[3]
            )) P
            GROUP BY SUBJECT

输出

SUBJECT 1   2   3
SUBJ1   20  15  15
SUBJ2   5   14  14
SUBJ3   30  29  29
SUBJ4   7   4   14