我有一个表结构是:
year | code | name| value | wef |
2014 | a001 | abe | 2000 | 2014-04-01 |
2014 | a001 | def | 3000 | 2014-05-01 |
2014 | a002 | abe | 2000 | 2014-06-01 |
2014 | a003 | def | 2000 | 2014-04-01 |
2014 | a003 | mno | 5000 | 2014-06-01 |
Run Code Online (Sandbox Code Playgroud)
我需要的结果格式为:
year | code | abe | abe__wef | def | def__wef | mno | mno____wef |
2014 | a001 | 2000|2014-04-01|3000 | 2014-05-01| |
2014 | a002 | 2000|2014-06-01| | | |
2014 | a003 | | |2000 | 2014-04-01| 5000| 2014-06-01
Run Code Online (Sandbox Code Playgroud)
您可以使用该PIVOT函数来获取结果,但由于您有多个要转换为列的值,因此您首先需要先查看value和wef列的逆透视。
您没有指定您使用的是哪个版本的 SQL Server,但您可以使用该UNPIVOT函数,也可以使用CROSS APPLYwithVALUES或UNION ALL将value/转换wef为多行。
语法类似于:
select year, code, col, val
from dbo.yourtable
cross apply
(
select name, convert(varchar(10), value) union all
select name+'_wef', convert(varchar(10), wef, 120)
) c (col, val);
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo。这会将您的数据转换为以下格式:
| YEAR | CODE | COL | VAL |
|------|------|---------|------------|
| 2014 | a001 | abe | 2000 |
| 2014 | a001 | abe_wef | 2014-04-01 |
| 2014 | a001 | def | 3000 |
| 2014 | a001 | def_wef | 2014-05-01 |
| 2014 | a002 | abe | 2000 |
| 2014 | a002 | abe_wef | 2014-06-01 |
Run Code Online (Sandbox Code Playgroud)
现在您可以应用该PIVOT功能:
select year, code,
abe, abe_wef, def, def_wef, mno, mno_wef
from
(
select year, code, col, val
from dbo.yourtable
cross apply
(
select name, convert(varchar(10), value) union all
select name+'_wef', convert(varchar(10), wef, 120)
) c (col, val)
) d
pivot
(
max(val)
for col in (abe, abe_wef, def, def_wef, mno, mno_wef)
) piv;
Run Code Online (Sandbox Code Playgroud)
使用上述版本可能会遇到的问题是,当您的值数量有限时,它非常有效,因为您可以对查询进行硬编码。但是,如果您有未知数量的值,则该解决方案将不起作用。在您有未知数量的值的情况下,您将需要使用动态 sql 来获得最终结果:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(col)
from dbo.yourtable
cross apply
(
select name, 1 union all
select name+'_wef', 2
) c (col, so)
group by col, so
order by col, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT year, code,' + @cols +N'
from
(
select year, code, col, val
from dbo.yourtable
cross apply
(
select name, convert(varchar(10), value) union all
select name+''_wef'', convert(varchar(10), wef, 120)
) c (col, val)
) x
pivot
(
max(val)
for col in (' + @cols + N')
) p '
exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo。两个版本都会给出以下结果:
| YEAR | CODE | ABE | ABE_WEF | DEF | DEF_WEF | MNO | MNO_WEF |
|------|------|--------|------------|--------|------------|--------|------------|
| 2014 | a001 | 2000 | 2014-04-01 | 3000 | 2014-05-01 | (null) | (null) |
| 2014 | a002 | 2000 | 2014-06-01 | (null) | (null) | (null) | (null) |
| 2014 | a003 | (null) | (null) | 2000 | 2014-04-01 | 5000 | 2014-06-01 |
Run Code Online (Sandbox Code Playgroud)