如何在这张桌子上计算工作时间?

时间:2015-12-19 08:32:55

标签: sql ms-access

我有一个具有以下结构的访问数据库

ID        EmployeeID        DateTime
1          250              29/11/2015 6:00:00 AM
2          251              29/11/2015 6:01:25 AM
3          252              29/11/2015 7:30:05 AM
4          250              29/11/2015 1:30:45 PM
5          252              29/11/2015 1:32:20 PM
6          251              29/11/2015 4:36:41 PM
7          250              30/11/2015 8:30:50 AM
8          250              30/11/2015 3:45:22 PM

此表存储每个员工进入或退出的时间。现在我想进行查询以获得这些数据:

第一个员工ID,接下来的两列是进入和退出时间

EmployeeID        DateTime                  DateTime2
250               29/11/2015 6:00:00 AM     29/11/2015 1:30:45 PM
251               29/11/2015 6:01:25 AM     29/11/2015 4:36:41 PM
252               29/11/2015 7:30:05 AM     29/11/2015 1:32:20 PM
250               30/11/2015 8:30:50 AM     30/11/2015 3:45:22 PM

请帮我进行此查询

3 个答案:

答案 0 :(得分:0)

可能不是最好的sql片段,但这肯定会给你什么样的后续

SELECT e1.EmployeeID, e1.[DateTime] As StartDateTime, e2.[DateTime] As EndDateTime
  FROM [EmployeeAccess] e1
    INNER JOIN [EmployeeAccess] e2 ON 
                     e1.Employeeid = e2.employeeid 
                     and e1.datetime <> e2.datetime 
                     and e1.DateTime < e2.datetime
                     and cast(e1.datetime as date) = cast(e2.datetime as date) 

将同一个表连同以下规则一起加入:

  1. 按EmployeeID匹配
  2. 确保日期时间不完全相同(删除相同条目的连接)
  3. 确保e1中的日期时间小于e2中的日期时间(删除e2大于e1的连接)
  4. 确保只匹配相同的日期条目(确保只加入当天的比赛)

答案 1 :(得分:0)

如果每位员工每天只有一个进入和退出时间,您可以按正确排序的日期进行分组:

Select 
    EmployeeID, 
    Min([DateTime]) As DateTime1, 
    Max([DateTime]) As DateTime2
From 
    YourLogTable
Group By 
    Fix([DateTime]),
    EmployeeID

答案 2 :(得分:0)

如果您每天有多个出入口,或者轮班可以进入第二天(过夜),您可以使用以下内容:

SELECT 
  T1.EmployeeID, 
  T1.DateTime as EntryTime, 
  Min(T2.DateTime) as ExitTime
FROM TheTable as T1 
  INNER JOIN TheTable as T2 
  ON (T1.EmployeeID = T2.EmployeeID AND T1.DateTime < T2.DateTime)
GROUP BY T1.DateTime, T1.EmployeeID
HAVING (count(T2.DateTime) mod2)=1;

只要您为每位员工的每个条目都有一个退出,这就有效。 如果你不能保证它有点麻烦但仍然可能:

SELECT 
  T1.EmployeeID, 
  T1.DateTime as EntryTime, 
  Min(T2.DateTime) as ExitTime
FROM (TheTable as T1 
  INNER JOIN TheTable as T2 
  ON (T1.EmployeeID = T2.EmployeeID AND T1.DateTime < T2.DateTime))
  INNER JOIN (
     SELECT EmployeeID, COUNT(DateTime) as EmployeeRecordCount FROM TheTable GROUP BY EmployeeID
     ) AS T3 ON T1.EmployeeID = T3.EmployeeID
GROUP BY T1.DateTime, T1.EmployeeID
HAVING ((count(T2.DateTime) mod 2)<>(FIRST(T3.EmployeeRecordCount) mod 2));

这是做什么的(对每个员工而言):

  • 将每条记录加入时间最短的记录: Min(T2.DateTime) as ExitTime

  • T1.DateTime < T2.DateTime
  • 然后加入此员工的条目总数: INNER JOIN (SELECT EmployeeID, COUNT(DateTime) as EmployeeRecordCount FROM TheTable GROUP BY EmployeeID) AS T3

  • 现在,如果EmployeeRecordCount为偶数,则只选择连接表T2具有不均匀DateTime数的行,反之亦然。

(ocurse HAVING ((count(T1.DateTime) mod 2)=(FIRST(T3.EmployeeRecordCount) mod 2))会给出相同的结果。)