从此查询中获取总持续时间?

时间:2017-12-12 09:07:38

标签: sql sql-server tsql

SQL Demo 这个我的表与demo中的相同,我使用相同的查询。我需要得到所有特定员工的总持续时间......我试了很多..

    select
       id, cast(time_stamp as date) [date]
     , format(max(case when in_rank = 1 then time_stamp end),'HH:mm') check_in_1
     , format(max(case when in_rank = 1 then next_timestamp end),'HH:mm') check_out_1
     , format(max(case when in_rank = 1 then 
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_1
     , format(max(case when in_rank = 2 then time_stamp end),'HH:mm') check_in_2
     , format(max(case when in_rank = 2 then next_timestamp end),'HH:mm') check_out_2
     , format(max(case when in_rank = 2 then
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_2
from (
      select
            id, time_stamp, AccessType, next_timestamp, next_accesstype
          , dense_rank() over(partition by id, cast(time_stamp as date) order by time_stamp) in_rank
      from table1 t1
      outer apply (
          select top(1) t2.time_stamp, t2.AccessType
          from table1 t2
          where t1.id = t2.id and t1.AccessType <> t2.AccessType
          and cast(t1.time_stamp as date) = cast(t2.time_stamp as date)
          and t1.time_stamp < t2.time_stamp
          order by t2.time_stamp
          ) oa (next_timestamp, next_accesstype)
      where AccessType = 0
     ) d
group by id, cast(time_stamp as date)

预期产出:

id  date    check_in_1  check_out_1 total_hrs_1 check_in_2  check_out_2 total_hrs_2  Grand Total
1001    2017-09-05      09:35       12:00       02:25     09:36     12:00       02:24     4:49
1002    2017-09-05      11:00       12:25       01:25     14:00     18:00       04:00     5:25

任何人都帮助我得到这个......我尝试了很多次

3 个答案:

答案 0 :(得分:0)

使用SQL Demo中的示例数据我已经修改了您的查询 - 请参阅代码中的注释

--I'm using a CTE only because to avoid the messy looking way of calculating the Grand total otherwise
;WITH cteX
AS(
    SELECT
           id, cast(time_stamp as date) [date]
         , format(max(case when in_rank = 1 then time_stamp end),'HH:mm') check_in_1
         , format(max(case when in_rank = 1 then next_timestamp end),'HH:mm') check_out_1
         , format(max(case when in_rank = 1 then 
               dateadd(SECOND,datediff(SECOND,time_stamp,next_timestamp),0)
               end),'HH:mm') total_hrs_1
         , format(max(case when in_rank = 2 then time_stamp end),'HH:mm') check_in_2
         , format(max(case when in_rank = 2 then next_timestamp end),'HH:mm') check_out_2
         , format(max(case when in_rank = 2 then
               dateadd(SECOND,datediff(SECOND,time_stamp,next_timestamp),0)
               end),'HH:mm') total_hrs_2
         --additional two rows here to represent the number of second between checkin and checkout
         , Total_hrs_1_secs = MAX(case when in_rank = 1 then 
               datediff(SECOND,time_stamp,next_timestamp)  end)
        , Total_hrs_2_secs = MAX(case when in_rank = 2 then
               datediff(SECOND,time_stamp,next_timestamp)  end)
    from (
          select
                id, time_stamp, AccessType, next_timestamp, next_accesstype
              , dense_rank() over(partition by id, cast(time_stamp as date) order by time_stamp) in_rank
          from table1 t1
          outer apply (
              select top(1) t2.time_stamp, t2.AccessType
              from table1 t2
              where t1.id = t2.id and t1.AccessType <> t2.AccessType
              and cast(t1.time_stamp as date) = cast(t2.time_stamp as date)
              and t1.time_stamp < t2.time_stamp
              order by t2.time_stamp
              ) oa (next_timestamp, next_accesstype)
          where AccessType = 0
         ) d
    group by id, cast(time_stamp as date)
)
SELECT X.id
     , X.date
     , X.check_in_1
     , X.check_out_1
     , X.total_hrs_1
     , X.check_in_2
     , X.check_out_2
     , X.total_hrs_2
      --show the Grant total using the seconds rows from above
     , GrandTotal = CONVERT(TIME(0), DATEADD(SECOND,(X.Total_hrs_1_secs + X.Total_hrs_2_secs),0),108) 
FROM cteX X

输出

enter image description here

答案 1 :(得分:0)

您在一天内有超过2对登录/注销,因此计算“in_row”以输出额外的登录/注销;

SQL Fiddle

MS SQL Server 2014架构设置

CREATE TABLE Table1
    ([id] int, [time_stamp] datetime, [AccessType] varchar(3))
;

INSERT INTO Table1
    ([id], [time_stamp], [AccessType])
VALUES
    (1001, '2017-09-05 09:35:00', 0),
    (1001, '2017-09-05 09:36:00', 0),
     (1001, '2017-09-05 09:37:00', 0),
    (1002, '2017-09-05 11:00:00', 0),
    (1001, '2017-09-05 12:00:00', 1),
    (1002, '2017-09-05 12:25:00', 1),
    (1001, '2017-09-05 13:00:00', 0),
    (1002, '2017-09-05 14:00:00', 0),
    (1001, '2017-09-05 17:00:00', 1),
    (1002, '2017-09-05 18:00:00', 1)
;

查询1

select
       id, in_row, cast(time_stamp as date) [date]
     , format(max(case when in_rank = 1 then time_stamp end),'HH:mm') check_in_1
     , format(max(case when in_rank = 1 then next_timestamp end),'HH:mm') check_out_1
     , format(max(case when in_rank = 1 then 
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_1
     , format(max(case when in_rank = 0 then time_stamp end),'HH:mm') check_in_2
     , format(max(case when in_rank = 0 then next_timestamp end),'HH:mm') check_out_2
     , format(max(case when in_rank = 0 then
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_2
     , format(max(case when in_rank = 0 then
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_2
     , format(dateadd(ss,sum(secs_diff),0),'HH:mm') total_hrs
from (
      select
            id, time_stamp, AccessType, next_timestamp, next_accesstype
          , datediff(ss,time_stamp,next_timestamp) secs_diff 
          , dense_rank() over(partition by id, cast(time_stamp as date) order by time_stamp) % 2 in_rank
          , (count(*) over(partition by id, cast(time_stamp as date) order by time_stamp) + 1) / 2 in_row
      from table1 t1
      outer apply (
          select top(1) t2.time_stamp, t2.AccessType
          from table1 t2
          where t1.id = t2.id and t1.AccessType <> t2.AccessType
          and cast(t1.time_stamp as date) = cast(t2.time_stamp as date)
          and t1.time_stamp < t2.time_stamp
          order by t2.time_stamp
          ) oa (next_timestamp, next_accesstype)
      where AccessType = 0
     ) d
group by id, in_row, cast(time_stamp as date)

<强> Results

|   id | in_row |       date | check_in_1 | check_out_1 | total_hrs_1 | check_in_2 | check_out_2 | total_hrs_2 | total_hrs_2 | total_hrs |
|------|--------|------------|------------|-------------|-------------|------------|-------------|-------------|-------------|-----------|
| 1001 |      1 | 2017-09-05 |      09:35 |       12:00 |       02:25 |      09:36 |       12:00 |       02:24 |       02:24 |     04:49 |
| 1001 |      2 | 2017-09-05 |      09:37 |       12:00 |       02:23 |      13:00 |       17:00 |       04:00 |       04:00 |     06:23 |
| 1002 |      1 | 2017-09-05 |      11:00 |       12:25 |       01:25 |      14:00 |       18:00 |       04:00 |       04:00 |     05:25 |

答案 2 :(得分:0)

这给出了上面提到的确切结果:

 select
       id, cast(time_stamp as date) [date]
     , format(max(case when in_rank = 1 then time_stamp end),'HH:mm') check_in_1
     , format(max(case when in_rank = 1 then next_timestamp end),'HH:mm') check_out_1
     , format(max(case when in_rank = 1 then 
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_1
     , format(max(case when in_rank = 2 then time_stamp end),'HH:mm') check_in_2
     , format(max(case when in_rank = 2 then next_timestamp end),'HH:mm') check_out_2
     , format(max(case when in_rank = 2 then
           dateadd(ss,datediff(ss,time_stamp,next_timestamp),0)
           end),'HH:mm') total_hrs_2
  , format(dateadd(ss,sum(secs_diff),0),'HH:mm') Total_Hrs
from (
      select
            id, time_stamp, AccessType, next_timestamp, next_accesstype, datediff(ss,time_stamp,next_timestamp) secs_diff 
          , dense_rank() over(partition by id, cast(time_stamp as date) order by time_stamp) in_rank
      from table1 t1
      outer apply (
          select top(1) t2.time_stamp, t2.AccessType
          from table1 t2
          where t1.id = t2.id and t1.AccessType <> t2.AccessType
          and cast(t1.time_stamp as date) = cast(t2.time_stamp as date)
          and t1.time_stamp < t2.time_stamp
          order by t2.time_stamp
          ) oa (next_timestamp, next_accesstype)
      where AccessType = 0
     ) d
group by id, cast(time_stamp as date)