这种类型的数据转换称为PIVOT
. 从 SQL Server 2005 开始,有一个函数可以为您执行此操作。
如果您提前知道这些值,则可以对查询进行硬编码,如下所示:
select *
from
(
select id,
[Emp_ID],
cast([ontime] as date) ontime
from test
) src
pivot
(
count(id)
for ontime in ([2013-02-11], [2013-02-12], [2013-02-13])
) piv
请参阅SQL Fiddle with Demo。
如果要转换的列数未知,则需要使用动态 SQL。这可以通过使用WHERE
子句进一步过滤以仅查找某些日期:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(cast([ontime] as date))
from test
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT emp_id,' + @cols + ' from
(
select Emp_ID pivId,
[Emp_ID],
cast([ontime] as date) ontime
from test
) x
pivot
(
count(pivId)
for ontime in (' + @cols + ')
) p '
execute(@query)
请参阅SQL Fiddle with Demo。
如果你想保证你会返回你想要的日期,那么你可以先生成一个日期列表。因此,您的整个动态 SQL 脚本将是:
declare @startdate datetime
declare @enddate datetime
set @startdate = '2013-02-11'
set @enddate = '2013-02-13'
;with cte (startdate) as
(
select @startdate
union all
select DATEADD(dd, 1, startdate)
from cte
where DATEADD(dd, 1, startdate) <= @enddate
)
select *
into #tempDates
from cte;
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(cast(startdate as date))
from #tempDates
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT emp_id,' + @cols + ' from
(
select Emp_ID pivId,
[Emp_ID],
cast([ontime] as date) ontime
from test
) x
pivot
(
count(pivId)
for ontime in (' + @cols + ')
) p '
execute(@query)
请参阅SQL Fiddle with Demo。这将返回结果:
| EMP_ID | 2013-02-11 | 2013-02-12 | 2013-02-13 |
-------------------------------------------------
| 1 | 2 | 0 | 1 |
| 2 | 1 | 0 | 1 |
| 3 | 0 | 0 | 1 |
编辑#1,如果您想包括所有员工,那么您将需要在另一个表上使用 JOIN 并且您的代码将与此类似:
declare @startdate datetime
declare @enddate datetime
set @startdate = '2013-02-11'
set @enddate = '2013-02-13'
;with cte (startdate) as
(
select @startdate
union all
select DATEADD(dd, 1, startdate)
from cte
where DATEADD(dd, 1, startdate) <= @enddate
)
select *
into #tempDates
from cte;
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(cast(startdate as date))
from #tempDates
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT emp_id, Emp_name,' + @cols + ' from
(
select e.Emp_ID pivId,
e.[Emp_ID],
e.Emp_name,
cast([ontime] as date) ontime
from Emp_Table e
left join test t
on e.emp_id = t.emp_id
) x
pivot
(
count(pivId)
for ontime in (' + @cols + ')
) p '
execute(@query)
请参阅带有演示的 SQL Fiddle