[英]how to convert row to column if unknown number of columns SQL server
I have data like this: 我有这样的数据:
MaGiangVienID | SoTiet1 | SoTiet2 | DateID
79000G07.000206 | 60 | 60.00 | t11
79000G07.000206 | 54 | 54.00 | t12
I want to my result like this: 我想要这样的结果:
MaGiangVienID | SoTiet1_t11 | SoTiet2_t11 | SoTiet1_t12 | SoTiet2_t12
79000G07.000206 | 60 | 60.00 | 54 | 54.00
I don't know how many columns because MaGiangVienID
have a lot of DateID
我不知道有多少列,因为
MaGiangVienID
有很多DateID
Please help me!!Thanks a lot. 请帮助我!非常感谢。
For this type of data transformation you need to apply both the UNPIVOT
and PIVOT
functions. 对于这种类型的数据转换,您需要同时应用
UNPIVOT
和PIVOT
函数。 The UNPIVOT
takes the data from the multiple columns and places it into rows and then the PIVOT
takes the rows and converts it back to columns. UNPIVOT
从多列中获取数据并将其放置到行中,然后PIVOT
从行中获取数据并将其转换回列中。
To perform the UNPIVOT
all of the values that you convert to rows must be the same datatype so conversion might be needed. 要执行
UNPIVOT
,您转换为行的所有值都必须是相同的数据类型,因此可能需要转换。
Unpivot : 取消枢纽 :
select MaGiangVienID,
value,
col +'_'+DateId col
from
(
select MaGiangVienID,
cast(SoTiet1 as varchar(50)) SoTiet1,
cast(SoTiet2 as varchar(50)) SoTiet2,
DateID
from yourtable
) src
unpivot
(
value
for col in (SoTiet1, SoTiet2)
) unpiv
See SQL Fiddle with Demo . 请参阅带有演示的SQL Fiddle 。 The result of the unpivot is:
取消透视的结果是:
| MAGIANGVIENID | VALUE | COL |
-----------------------------------------
| 79000G07.000206 | 60 | SoTiet1_t11 |
| 79000G07.000206 | 60.00 | SoTiet2_t11 |
| 79000G07.000206 | 54 | SoTiet1_t12 |
| 79000G07.000206 | 54.00 | SoTiet2_t12 |
As you see the UNPIVOT
generates the new column names with the DateId
appended to the end of it. 如您所见,
UNPIVOT
生成新列名,并在其DateId
附加DateId
。 Now you apply the PIVOT
function. 现在,您将应用
PIVOT
功能。
Static PIVOT: 静态PIVOT:
select MaGiangVienID, SoTiet1_t11, SoTiet2_t11, SoTiet1_t12, SoTiet2_t12
from
(
select MaGiangVienID,
value,
col +'_'+DateId col
from
(
select MaGiangVienID,
cast(SoTiet1 as varchar(50)) SoTiet1,
cast(SoTiet2 as varchar(50)) SoTiet2,
DateID
from yourtable
) src
unpivot
(
value
for col in (SoTiet1, SoTiet2)
) unpiv
) src
pivot
(
max(value)
for col in (SoTiet1_t11, SoTiet2_t11, SoTiet1_t12, SoTiet2_t12)
) piv
See SQL Fiddle with Demo 参见带有演示的SQL Fiddle
Now the above version works great if you have a known number of DateId
values but you stated that you don't so you will want to implement this same query using dynamic sql. 现在,如果您拥有已知数量的
DateId
值,但上面的版本非常DateId
但您声明了不这样的说法,那么您将希望使用动态sql实现相同的查询。
Dynamic PIVOT: 动态PIVOT:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@colsPivot as NVARCHAR(MAX)
select @colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('yourtable') and
C.name not in ('MaGiangVienID', 'DateID')
for xml path('')), 1, 1, '')
select @colsPivot = STUFF((SELECT DISTINCT ','
+ quotename(c.name + '_'+t.DateId)
from yourtable t
cross apply sys.columns as C
where C.object_id = object_id('yourtable') and
C.name not in ('MaGiangVienID', 'DateID')
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= 'select MaGiangVienID, '+@colsPivot+'
from
(
select MaGiangVienID, value, col +''_''+DateId col
from
(
select MaGiangVienID,
cast(SoTiet1 as varchar(50)) SoTiet1,
cast(SoTiet2 as varchar(50)) SoTiet2,
DateID
from yourtable
) src
unpivot
(
value
for col in ('+@colsUnpivot+')
) unpiv
) src
pivot
(
max(value)
for col in ('+ @colspivot +')
) p'
exec(@query)
See SQL Fiddle with Demo 参见带有演示的SQL Fiddle
Both versions produce the same result: 两种版本产生相同的结果:
The result is: 结果是:
| MAGIANGVIENID | SOTIET1_T11 | SOTIET2_T11 | SOTIET1_T12 | SOTIET2_T12 |
---------------------------------------------------------------------------
| 79000G07.000206 | 60 | 60.00 | 54 | 54.00 |
If you do not have access to the UNPIVOT
/ PIVOT
functions then you can replicate the query. 如果您无权使用
UNPIVOT
/ PIVOT
函数,则可以复制查询。 The UNPIVOT
function can be replicated using a UNION ALL
and the PIVOT
can be produced using a CASE
statement with an aggregate function: 可以使用
UNION ALL
复制UNPIVOT
函数,并可以使用带有聚合函数的CASE
语句生成PIVOT
:
select MaGiangVienID,
max(case when col = 'SoTiet1_t11' then value end) SoTiet1_t11,
max(case when col = 'SoTiet2_t11' then value end) SoTiet2_t11,
max(case when col = 'SoTiet1_t12' then value end) SoTiet1_t12,
max(case when col = 'SoTiet2_t12' then value end) SoTiet2_t12
from
(
select MaGiangVienID, 'SoTiet1_t11' col, cast(SoTiet1 as varchar(50)) value
from yourtable
where DateID = 't11'
union all
select MaGiangVienID, 'SoTiet2_t11' col, cast(SoTiet2 as varchar(50)) value
from yourtable
where DateID = 't11'
union all
select MaGiangVienID, 'SoTiet1_t12' col, cast(SoTiet1 as varchar(50)) value
from yourtable
where DateID = 't12'
union all
select MaGiangVienID, 'SoTiet2_t12' col, cast(SoTiet2 as varchar(50)) value
from yourtable
where DateID = 't12'
) src
group by MaGiangVienID
See SQL Fiddle with Demo 参见带有演示的SQL Fiddle
All versions will produce identical results. 所有版本将产生相同的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.