简体   繁体   中英

Pivoting Timelogs in Sql Query

I am kind of stuck in querying my timelogs table, the following are the sample data:

TimelogId     EmployeeId     RecordDate     RecordTime     Type
---------     ----------     ----------     ----------     ----
   1              4          2016-07-01     07:18:37         1
   2              4          2016-07-01     12:03:14         2
   5              4          2016-07-01     12:08:02         1
   6              4          2016-07-01     18:02:03         2
   7              6          2016-07-19     07:24:15         1
   8              5          2016-07-19     07:26:03         1
   9              6          2016-07-19     12:15:26         2
   10             5          2016-07-19     12:35:17         2
   13             5          2016-07-19     12:36:14         1
   16             6          2016-07-19     12:45:45         1
   17             6          2016-07-19     17:10:22         2
   18             5          2016-07-19     18:43:09         2

The required output:

   Date      EmployeeId    Time_In      Time_Out      Time_In      Time_Out
  -------    ----------    --------     --------      -------      -------
2016-07-01       4         07:18:37     12:03:14      12:08:03    18:02:03
2016-07-19       6         07:24:15     12:15:26      12:45:45    17:10:22
2016-07-19       5         07:26:03     12:35:17      12:36:14    18:43:08

Where Type (1) = time in and Type (2) = time out.

Employees are required to logout at 12nn then log back in again after a couple of minutes.

I tried using pivot based from the previous questions that i read here. Though this is the first time i tried to use pivot in tables.

select 
*
FROM
(
  select 
  EmployeeID,
  RecordDate,
  RecordTime,
  Type
  from tblTimeLogs
) d
PIVOT(
  Max(RecordTime) <---- I think the problem is right around here
  FOR Type in ([1],[2]) <----- plus i can't seem to rename this column names maybe i'll read a little further on this.
) piv;                        

Output of query:

EmployeeID          RecordDate          1                2
----------          ----------        ------          ------
    4               2016-07-01       12:08:02        18:02:03
    5               2016-07-19       12:36:14        18:43:09
    6               2016-07-19       12:45:45        17:10:22

is this possible? Thanks. :D

Edit:

as suggested by vercelli, another scenario like for example the user forgot that he/she already timed in just a couple of minutes ago so she timed in again. eg

TimelogId     EmployeeId     RecordDate     RecordTime     Type
---------     ----------     ----------     ----------     ----
   1              4          2016-07-01     07:18:37         1
   2              4          2016-07-01     12:03:14         2
   5              4          2016-07-01     12:08:02         1
   6              4          2016-07-01     18:02:03         2
   7              6          2016-07-19     07:24:15         1
   8              5          2016-07-19     07:26:03         1
   9              6          2016-07-19     12:15:26         2
   10             5          2016-07-19     12:35:17         2
   13             5          2016-07-19     12:36:14         1
   16             6          2016-07-19     12:45:45         1
   17             6          2016-07-19     17:10:22         2
   18             5          2016-07-19     18:43:09         2
   19             5          2016-07-20     08:13:35         1  <--- Time in
   20             5          2016-07-20     08:14:35         1  <--- Timed In again
   21             5          2016-07-20     12:15:12         2  <--- Time Out

I tried using the query of Mr. Vercelli:

select 
EmployeeID as Emp, RecordDate, [1] as Time_In1, [2] as Time_Out1, [3] as Time_In2, [4] as Time_out2
FROM
(
  select 
  EmployeeID,
  RecordDate,
  RecordTime,
  ROW_NUMBER () over (partition by EmployeeId, RecordDate order by RecordTime, type) as rn
from tblTimeLogs
) d
PIVOT(
  max(RecordTime)
  FOR rn in ([1],[2],[3],[4])
) as piv;  

Output of the new query:

 Emp   RecordDate    Time_In1    Time_Out1    Time_In2     Time_Out2
 ----  ----------    ---------   ---------    --------     ---------
  4    2016-07-01    07:18:37    12:03:14     12:08:02     18:02:03
  5    2016-07-19    07:26:03    12:35:17     12:36:14     18:43:09
  5    2016-07-20    08:13:35    08:14:35     12:15:12       Null <--- the problem is right around this portion
  6    2016-07-19    07:24:15    12:15:26     12:45:45     17:10:22

Expected Output:

  Emp   RecordDate    Time_In1    Time_Out1    Time_In2    Time_Out2
 ----  ----------    ---------   ---------    --------     ---------
  4    2016-07-01    07:18:37    12:03:14     12:08:02     18:02:03
  5    2016-07-19    07:26:03    12:35:17     12:36:14     18:43:09
  5    2016-07-20    08:13:35    12:15:12     08:14:35       Null <--- the second time in would fall on the second 5th column (Time_In2) since the **Type** value is = 1      
  6    2016-07-19    07:24:15    12:15:26     12:45:45     17:10:22

Thanks for the help guys :D. I'm learning new things from this problem.

I think this is what you are looking for. Demo :

select 
EmployeeID as Emp, RecordDate, [1] as Time_In1, [2] as Time_Out1, [3] as Time_In2, [4] as Time_out2
FROM
(
  select 
  EmployeeID,
  RecordDate,
  RecordTime,
  ROW_NUMBER () over (partition by EmployeeId, RecordDate order by RecordTime, type) as rn
  from tblTimeLogs
) d
PIVOT(
  max(RecordTime)
  FOR rn in ([1],[2],[3],[4])
) as piv;  

OUPUT

Emp RecordDate  Time_In1    Time_Out1   Time_In2    Time_out2
4   2016-07-01  07:18:37    12:03:14    12:08:02    18:02:03
5   2016-07-19  07:26:03    12:35:17    12:36:14    18:43:09
6   2016-07-19  07:24:15    12:15:26    12:45:45    17:10:22

DEMO HERE

---Table Creattion Scripts

 create table #test
   (
   employeeid int,
   recorddate date,
   recordtime time,
   typee int
   )

insert into #test  values(    4 ,         '2016-07-01',     '07:18:37',         1)
insert into #test  values(    4 ,         '2016-07-01',     '12:03:14',         2)
insert into #test  values(    4 ,         '2016-07-01',     '12:08:02',         1)
insert into #test  values(    4 ,         '2016-07-01',     '18:02:03',         2)

Query

 ;with cte
 as
 (
select
 employeeid,
 max(recorddate) as recorddate,
 min(recordtime) as timein,
max(recordtime) as Timein1 ,
 lead(min(recordtime)) over (partition by employeeid order by min(recordtime)) as 'timeout1',
 lead(max(recordtime)) over (partition by employeeid order by max(recordtime)) as 'timeout2'
 from #test
 group by 
 employeeid,typee
)
    select employeeid,recorddate,timein,timeout1,timein1,timeout2
    from cte
    where timeout1 is not null and timeout2 is not null

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM