将 SQL 表中的数据从行列转换为列行的好方法有哪些?
还允许在初始查询上应用过滤器/位置条件。
使用 SQL Server 2008。
现有表具有以下列:AID(nvarchar 唯一)ASID(nvarchar 唯一)里程碑(M1、M2、M3...M100)里程碑日期(日期时间)
转置数据如下:AID、ASID、M1 日期、M2 日期、M3 日期、M5 日期
将 SQL 表中的数据从行列转换为列行的好方法有哪些?
还允许在初始查询上应用过滤器/位置条件。
使用 SQL Server 2008。
现有表具有以下列:AID(nvarchar 唯一)ASID(nvarchar 唯一)里程碑(M1、M2、M3...M100)里程碑日期(日期时间)
转置数据如下:AID、ASID、M1 日期、M2 日期、M3 日期、M5 日期
如果您使用的是 SQL Server 2005+,那么您有几个选项可以转置数据。您可以实现PIVOT
类似这样的功能:
select AID, ASID,
M1 as M1_Date, M2 as M2_Date,
M3 as M3_Date, M4 as M4_Date, M5 as M5_Date
from
(
select AID, ASID, Milestone,
MilestoneDate
from yourtable
where AID = whatever -- other filters here
) src
pivot
(
max(milestonedate)
for milestone in (M1, M2, M3, M4, M5...)
) piv
或者您可以使用带有CASE
语句的聚合函数:
select aid,
asid,
max(case when milestone = 'M1' then milestonedate else null end) M1_Date,
max(case when milestone = 'M2' then milestonedate else null end) M2_Date,
max(case when milestone = 'M3' then milestonedate else null end) M3_Date,
max(case when milestone = 'M4' then milestonedate else null end) M4_Date
from yourtable
where AID = whatever -- other filters here
group by aid, asid
milestone
如果您有已知数量的值,则上述两个查询效果很好。但如果没有,那么你可以实现动态 sql 来转置数据。动态版本将与此类似:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@colNames AS NVARCHAR(MAX),
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Milestone)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colNames = STUFF((SELECT distinct ',' + QUOTENAME(Milestone+'_Date')
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT AID, ASID,' + @colNames + ' from
(
select AID, ASID, Milestone,
MilestoneDate
from yourtable
where AID = whatever -- other filters here
) x
pivot
(
max(MilestoneDate)
for Milestone in (' + @cols + ')
) p '
execute(@query)
这是一种相当通用的方法:
select
aid, asid,
max (case when milestone = 'M1' then milestonedate else null end) M1Date,
max (case when milestone = 'M2' then milestonedate else null end) M2Date,
max (case when milestone = 'M3' then milestonedate else null end) M3Date,
max (case when milestone = 'M5' then milestonedate else null end) M5Date
from
mytable
group by aid, asid