我有下表:
--------------------------------------------
Group Date Value1 Value2 Value3
--------------------------------------------
A 2014-01-01 10 10 5
B 2014-01-01 12 20 25
C 2014-01-01 20 40 50
我希望得到以下结果:
-------------------------------------------
NewCol A B C
-------------------------------------------
Value1 10 12 20
Value2 10 20 40
Value3 5 25 50
如何在sql server 2008中执行此操作?谢谢。
答案 0 :(得分:1)
您可以使用PIVOT运算符。请参阅以下详细信息:
select 'Value1' NewCol, A, B, C
from (select [Group], Value1 Value from YourTable) g
pivot (
max(g.Value)
for g.[Group] in (A, B, C)) p
union all
select 'Value2', A, B, C
from (select [Group], Value2 Value from YourTable) g
pivot (
max(g.Value)
for g.[Group] in (A, B, C)) p
union all
select 'Value3', A, B, C
from (select [Group], Value3 Value from YourTable) g
pivot (
max(g.Value)
for g.[Group] in (A, B, C)) p
或者您可以组合PIVOT和UNPIVOT运算符:
select NewCol, A, B, C
from (
select *
from YourTable
unpivot (
Value
for NewCol in (Value1, Value2, Value3)
) up
) up
pivot (
max(Value)
for [Group] in (A, B, C)
) p
答案 1 :(得分:1)
要交换行和列,您需要先UNPIVOT
(将列转换为行值),然后根据PIVOT
结果UNPIVOT
(行到列)。
-- Here is the result
SELECT * FROM
(
-- Unpivot here using CROSS APPLY
SELECT [Group],
[Values],COLNAMES
FROM YOURTABLE
CROSS APPLY(VALUES (Value1,'Value1'),(Value2,'Value2'),(Value3,'Value3'))
AS COLUMNNAMES([Values],COLNAMES)
)TAB
PIVOT
(
-- Specify the values to hold in pivoted column
MIN([Values])
-- Specify the name of columns
FOR [Group] IN([A],[B],[C])
)P
ORDER BY COLNAMES
查询的工作
您可以CROSS APPLY
使用UNPIVOT
。 Value1
将保留列中的值 - Value1
。 'Value1'
(在单引号中)将是硬编码列名称值(显示在COLNAMES
变量中。CROSS APPLY
的使用将生成以下结果。
现在使用CROSS APPLY
生成的数据,您将转到PIVOT
,形成以下结果。
有时您无法事先知道列Group
中的值。在这种情况下,您需要使用Dynamic Sql
。第一步是将行Group
中的值变为变量。
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = STUFF((SELECT ',' + QUOTENAME([Group])
FROM
(
SELECT distinct [Group] from YOURTABLE
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
现在使用PIVOT
查询Dynamic Sql
。我们使用Dynamic Sql
的原因是因为Sql Server
无法从变量中获取列名,除非使用Dynamic Sql
。
DECLARE @query NVARCHAR(MAX)
SET @query = '
SELECT * FROM
(
-- Unpivot here using CROSS APPLY
SELECT [Group],
[Values],COLNAMES
FROM YOURTABLE
CROSS APPLY(VALUES (Value1,''Value1''),(Value2,''Value2''),(Value3,''Value3''))
AS COLUMNNAMES([Values],COLNAMES)
) x
PIVOT
(
-- Specify the values to hold in pivoted column
MIN([Values])
-- Get the column names from variable
FOR [Group] IN('+@cols+')
) p
ORDER BY COLNAMES;'
EXEC SP_EXECUTESQL @query
希望您了解概念并获得结果 任何澄清,随时可以询问。
答案 2 :(得分:0)
使用PIVOT
功能。那会给你答案。
PIVOT
功能
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
检查此参考文献:Click Here
答案 3 :(得分:0)
您需要UNPIVOT
:
DECLARE @t TABLE
(
G CHAR(1) ,
V1 INT ,
V2 INT ,
V3 INT
)
INSERT INTO @t
VALUES ( 'A', 10, 10, 5 ),
( 'B', 12, 20, 25 ),
( 'C', 20, 40, 50 );
WITH cte1
AS ( SELECT *
FROM @t
WHERE G = 'A'
),
cte2
AS ( SELECT *
FROM @t
WHERE G = 'B'
),
cte3
AS ( SELECT *
FROM @t
WHERE G = 'C'
)
SELECT u1.v ,
u1.a ,
u2.b ,
u3.c
FROM ( SELECT *
FROM cte1 UNPIVOT( a FOR v IN ( [V1], [V2], [V3] ) ) u
) u1
JOIN ( SELECT *
FROM cte2 UNPIVOT( b FOR v IN ( [V1], [V2], [V3] ) ) u
) u2 ON u1.v = u2.v
JOIN ( SELECT *
FROM cte3 UNPIVOT( c FOR v IN ( [V1], [V2], [V3] ) ) u
) u3 ON u2.v = u3.v
输出:
v a b c
V1 10 12 20
V2 10 20 40
V3 5 25 50