Reputation: 27
I have a table with the following structure recording employees arrival and dispersal times:
What I'm hoping to achieve in a query/stored procedure is a pivot type data return between date ranges as per bottom grid on the attached image.
Could I kindly ask your expertise or sample on how to get it done? I have been researching however all my efforts have been fruitless.
Upvotes: 1
Views: 17717
Reputation: 1
I would add a DISTINCT on the following line:
select @cols - select @cols = stuff((select DISTINCT ',' + ....
Upvotes: -1
Reputation: 247880
You can use the PIVOT function to get the final result but since you are aggregating a string
/time
value, then you will also need to use a windowing function like row_number()
to return multiple rows for each userid
/datein
combination.
I would use a subquery similar to the following to return your data with a unique sequence number for each userid
/datein
combo:
select name,
datein = convert(varchar(10), datein, 120),
dttime = cast(timein as varchar(5)) + ' - '+ cast(timeout as varchar(5)),
row_number() over(partition by userid, datein order by datein) seq
from dbo.yourtable;
Once you have this data, then you can easily apply the pivot:
select name, [2013-04-10]
from
(
select name,
datein = convert(varchar(10), datein, 120),
dttime = cast(timein as varchar(5)) + ' - '+ cast(timeout as varchar(5)),
row_number() over(partition by userid, datein order by datein) seq
from dbo.yourtable
) d
pivot
(
max(dttime)
for datein in ([2013-04-10])
) piv;
Then if you have an unknown number of values, then you will want to use dynamic SQL:
DECLARE
@cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@startdate datetime,
@enddate datetime,
@paramdef nvarchar(max)
set @startdate = '2013-02-01'
set @enddate = '2013-05-10';
set @paramdef = '@startdate datetime, @enddate datetime';
select @cols = STUFF((SELECT ',' + QUOTENAME(convert(varchar(10), datein, 120))
from dbo.yourtable
where datein > @startdate
and datein <= @enddate
group by datein
order by datein
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = N'SELECT name, '+ @cols + '
from
(
select name,
datein = convert(varchar(10), datein, 120),
dttime = cast(timein as varchar(5)) + '' - ''+ cast(timeout as varchar(5)),
row_number() over(partition by userid, datein order by datein) seq
from dbo.yourtable
where datein > @startdate
and datein <= @enddate
) x
pivot
(
max(dttime)
for datein in ('+@cols+')
) p '
exec sp_executesql @query, @paramdef, @startdate = @startdate, @enddate = @enddate;
Upvotes: 3