SQL匹配员工班次的员工intime(打卡时间)

时间:2014-07-22 01:52:25

标签: sql sql-server sql-server-2008 stored-procedures

我有一个存储过程,用于检索员工每日摘要及时:

SELECT ads.attendancesumid,
       ads.employeeid,
       ads.date,
       ads.day, -- month day number
       ads.intime,
       ads.outtime
       --employee shift intime and outtime
       ss.intime,
       ss.outtime
  FROM employee_attendance_daily_summary ads
  JOIN employee emp
    ON emp.employeeid = ads.employeeid
  JOIN setup_shift ss
    ON ss.shiftcode = emp.shiftcode
   AND DATEPART(dw, ads.date) = ss.day
 WHERE ads.employeeid = 4 -- just to filter one employee

查询结果如下:

enter image description here

每个day重复 3次,因为表setup_shift(员工轮班)有:

  

周一至周日有3种不同的班次类型: DAY AFTERNOON NIGHT

以下是相同的信息,但使用班次类型列:

enter image description here

  

我需要的是每天获得1行,但最近的员工班次取决于intimeouttime

所以欲望结果应该是这样的:

enter image description here

有关如何做到这一点的任何线索?提前欣赏它。

我还有intime 00:00:00outtime有值的情况:

enter image description here

更新

这里是SQL FIDDLE

http://sqlfiddle.com/#!6/791cb/7

3 个答案:

答案 0 :(得分:0)

如果时间是在午夜之后的几秒钟内,而不是timedatetime或字符串格式,则会更容易。您可以使用以下公式转换它们:

select datepart(hour, intime) * 3600 + datepart(minute, intime) * 60 + datepart(second, intime)

(部分原因是我对处理其他数据类型所需的所有嵌套函数感到不舒服。)

所以,让我假设您有一系列类似的列,以秒为单位。然后,您可以通过对每个班次进行重叠并选择具有最大重叠的班次来解决此问题。

with t as (
      <your query here>
     ),
     ts as (
      select t.*,
             (datepart(hour, ads.intime) * 3600 + datepart(minute, ads.intime) * 60 + 
              datepart(second, ads.intime)
             ) as e_intimes,
             . . .
      from t
     ),
     tss as (
      select ts.*,
             (case when e_intimes >= s_outtimes then 0
                   when e_outtimes <= s_inttimes then 0
                   else (case when e_outtimes < s_outtimes then e_outtimes else s_outtimes end) -
                        (case when e_intimes > s_intimes then e_intimes else s_intimes end)
              end) as overlap
      from ts
     )
select ts.*
from (select ts.*,
             row_number() over (partition by employeeid, date
                                order by overlap desc
                               ) as seqnum
      from ts
     ) ts
where seqnum = 1;

答案 1 :(得分:0)

select ads.attendancesumid,
       ads.employeeid,
       ads.date,
       ads.day,
       ads.intime,
       ads.outtime,
       ss.intime,
       ss.outtime
  from employee_attendance_daily_summary ads
  join employee emp
    on emp.employeeid = ads.employeeid
  join setup_shift ss
    on ss.shiftcode = emp.shiftcode
   and datepart(dw, ads.date) = ss.day
 where ads.employeeid = 4
   and ((abs(datediff(hh,
                      cast(ads.intime as datetime),
                      cast(ss.intime as datetime))) between 0 and 2) or
       (ads.intime = '00:00:00' and
       ss.intime =
       (select min(x.intime)
            from setup_shift x
           where x.shiftcode = ss.shiftcode
             and x.intime > (select min(y.intime)
                               from setup_shift y
                              where y.shiftcode = x.shiftcode))))

答案 2 :(得分:0)

试试这个男人,我只考虑每组datediff(mi,intime,shift_intime)

的最小时差
Select * from 
(select 
row_number() over(partition by employeeid 
                   order by datediff(mi,intime,shift_intime) asc) as id,
attendance,employeeid,date,day,intime,outime,shiftintime,shiftoutime from table
 )
where id=1