Question

I have a table with the following structure recording employees arrival and dispersal times:

enter image description here

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.

Was it helpful?

Solution

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;

OTHER TIPS

I would add a DISTINCT on the following line:

select @cols - select @cols = stuff((select DISTINCT ',' + ....
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top