plz Solve My Table test
Id int Emp_ID int ontime Datetime
从测试中选择*
Id Emp_ID ontime 1 1 2013-02-11 2:14:25.387 2 2 2013-02-11 14:14:25.387 1 1 2013-02-11 20:14:25.387 3 3 2013-02-13 10:14:25.387 4 2 2013-02-13 10:14:25.387 5 1 2013-02-13 10:14:25.387 6 1 2013-02-14 11:14:25.387
我的要求这个
用户输入两个日期并记录每日显示计数
只记录
日期1 = 11/2/2013 日期2 = 13/2/2013
Emp_ID 11/2/2013 12/2/2013 13/2/2013 1 2 0 1 2 1 0 1 3 0 0 1
thx
THX
但是这一个tbl_emp
Emp_ID int Emp_name varchar
| EMP_ID | 2013-02-11 | 2013-02-12 | 2013-02-13 | ------------------------------------------------- | 1 | 2 | 0 | 1 | | 2 | 1 | 0 | 1 | | 3 | 0 | 0 | 1 | | 4 | 0 | 0 | 0 |
Emp_ID 4未插入测试表
答案 0 :(得分:3)
此类数据转换称为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。这可以通过使用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脚本将是:
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)