Tsql 查询时间卡数据库

Tsql 查询时间卡数据库,tsql,Tsql,我有一个时间表供员工打卡进出,布局如下: employeeID Clock-in DateTime Clock Type 1004 24/09/2013 13:08 in 1004 25/09/2013 00:50 out 1005 24/09/2013 12:08 in 1005 25/09/2013 03:55 out 2003 24/09/2013 10:06 in 2003

我有一个时间表供员工打卡进出,布局如下:

employeeID  Clock-in DateTime   Clock Type
1004        24/09/2013 13:08    in
1004        25/09/2013 00:50    out
1005        24/09/2013 12:08    in
1005        25/09/2013 03:55    out
2003        24/09/2013 10:06    in
2003        24/09/2013 15:42    out
2003        24/09/2013 17:33    in
2003        24/09/2013 22:17    out
我怎样才能让它像:

Date        employeeID  Clock-in            Clock-out           time worked (in hours to 2 decimal place)
24/09/2013  1004        24/09/2013 13:08    25/09/2013 00:50    xx.xx
24/09/2013  1005        24/09/2013 12:08    25/09/2013 03:55    xx.xx
24/09/2013  2003        24/09/2013 10:06    24/09/2013 15:42    xx.xx
24/09/2013  2003        24/09/2013 17:33    24/09/2013 22:17    xx.xx
注:

员工可以有多个上班/下班时间,即早班/下午班、夜班 日期从04:00:00到03:59:59,即在上述示例中,所有日期均归类为2013年9月24日 我如何处理没有打卡的记录?我是否可以设置为空,时间等于下一个日期03:59:59? 提前谢谢

我根据jods的建议更新了以下内容:

3组输入/输出记录示例

EmployeeID  CardDate            PunchType
1000        21/09/2013 07:43    in
1000        21/09/2013 11:29    out
1000        21/09/2013 12:39    in
1000        21/09/2013 20:37    out
1000        21/09/2013 21:58    in
1000        22/09/2013 00:16    out
您的查询返回

Date        EmployeeID  clockInTime clockOutTime
21/09/2013  1000        07:43:57    00:16:22
21/09/2013  1000        21:58:40    11:29:22

如果您使用SQL SERVER 2005及更高版本。你可以试试这个

WITH cte AS (
SELECT
   [employeeID]
    ,ti.ClockIn
    ,ClockOut = (SELECT MIN(t.ClockIn) 
                 FROM timecard t 
                 WHERE ti.employeeID = t.employeeID 
                 AND t.Type = 'out' 
                 AND t.ClockIn > ti.ClockIn
                 AND t.ClockIn < DATEADD(hour, 24 + 4 , CAST(CAST(ti.ClockIn AS DATE) AS datetime))
                )  
    ,NextDayLimit = DATEADD(SECOND, -1, DATEADD(hour, 24 + 4 , CAST(CAST(ti.ClockIn AS DATE) AS datetime)))
FROM timecard ti
WHERE Type = 'in'
)
SELECT 
    employeeID,
    ClockIn,
    ISNULL(ClockOut, NextDayLimit) AS ClockOut,
    CAST(DATEDIFF(minute, ClockIn, ISNULL(ClockOut, NextDayLimit))/60.0 AS NUMERIC(19,2)) AS TimeWorked
from cte
ORDER BY    employeeID, ClockIn

如果您使用SQL 2012,以下是使用LEAD的基本思想:

SELECT 
   ROUND(clockIn) as [date],
   employeeId,
   clockIn as clockInTime,
   LEAD(clockIn) OVER (PARTITION BY employeeId, ROUND(clockIn) ORDER BY clockIn) as clockOutTime
FROM TimeCard
WHERE clockType = 'in'
然后,您可以通过计算时钟输入和时钟输出时间之间的差异来获得时间

这里有很多拐弯处的案例,但并非全部都在这里处理:

工作时间能跨越午夜吗? 如果第一个时钟输入是“输出”类型,该怎么办? 如果一排有两个“进”或两个“出”怎么办? 不过,没有打卡的情况是可以处理的。因为分区的最后一行的前导值为NULL

在SQL 2005中,有一个更健壮的选项:

WITH NumberedClockIn AS (
  SELECT 
    ROUND(clockIn) as [date],
    employeeId,
    clockIn as clockTime,
    clockType,
    ROW_NUMBER() OVER (PARTITION BY employeeId, ROUND(clockIn) ORDER BY clockIn) as rn
  FROM TimeCard
)
SELECT 
  IN.[date], 
  IN.employeeId, 
  IN.clockTime as clockInTime,
  OUT.clockTime as clockOutTime
FROM NumberedClockIn IN
LEFT OUTER JOIN NumberedClockIn OUT
  ON IN.[date] = OUT.[date]
 AND IN.employeeId = OUT.employeeID
 AND IN.rn + 1 = OUT.rn
WHERE IN.clockType = 'in'
  AND OUT.clockType = 'out'

它更复杂,效率更低,但在面对无效的“输入”和“输出”序列时更健壮。同样,它处理无效序列的方式可能是,也可能不是您真正想要的行为。

此表上没有PK吗?或者一个给定的员工是否可以在一分钟内不打卡,从而使整个记录唯一。您使用的是哪个版本的sqlserver?表中有一个主键,但它是以某种方式散列的。时钟输入和时钟输出都是秒,因此每个记录都是唯一的。我们使用的是SQL server 2008标准r2I尝试了您的解决方案,该解决方案适用于最多有2条时钟输入/时钟输出4条记录的员工,但我有一名员工有3套时钟输入/时钟输出,并且输入和输出记录中存在不匹配。我已经把一些原始数据样本和返回的结果集提交给您参考