比较两个不同的表,找出不匹配的时间戳

时间:2017-12-20 13:38:09

标签: sql sql-server sql-server-2012

我想知道一名员工在工作时间内外办公室的工作时数。

以下是员工的工作时间

案例#1

FromDateTime                ToDateTime
---------------------------------------------------
2017-12-11 07:30:00.000     2017-12-11 12:30:00.000
2017-12-11 15:30:00.000     2017-12-11 18:30:00.000

以下是员工的出勤时间(办公时间内)

InTime                          OutTime
--------------------------------------------------------
2017-12-11 07:30:12.000         2017-12-11 07:34:29.000
2017-12-11 12:45:28.000         2017-12-11 13:04:15.000
2017-12-11 17:55:15.000         2017-12-11 18:04:28.000

当您比较上述两个表时,预期的内部和外部时间与工作时间的关系应低于:

FromTime                    ToTime                      Remarks
-----------------------------------------------------------------------
2017-12-11 07:30:12.000     2017-12-11 07:34:29.000     Inside Office
2017-12-11 07:34:29.000     2017-12-11 12:30:00.000     Outside Office
2017-12-11 12:45:28.000     2017-12-11 13:04:15.000     Inside Office
2017-12-11 15:30:00.000     2017-12-11 17:55:15.000     Outside Office
2017-12-11 17:55:15.000     2017-12-11 18:04:28.000     Inside Office
2017-12-11 18:04:28.000     2017-12-11 18:30:00.000     Outside Office

但我得到的结果为:

FromTime                    ToTime                      Remarks
-----------------------------------------------------------------------
2017-12-11 07:30:00.000     2017-12-11 07:30:12.000     Outside Office
2017-12-11 07:30:12.000     2017-12-11 07:34:29.000     Inside Office
2017-12-11 07:34:29.000     2017-12-11 12:45:28.000     Outside Office
2017-12-11 12:45:28.000     2017-12-11 13:04:15.000     Inside Office
2017-12-11 15:30:00.000     2017-12-11 17:55:15.000     Outside Office
2017-12-11 17:55:15.000     2017-12-11 18:04:28.000     Inside Office
2017-12-11 18:04:28.000     NULL                        Outside Office

我希望我清除了我的问题,下面是我为此目的编写的查询:

DECLARE @EmployeeDutyHours TABLE  
(
    FromDateTime DATETIME,
    ToDateTime DATETIME
)

DECLARE @EmployeeAttendanceHours TABLE  
(
    InTime DATETIME,
    OutTime DATETIME
)

INSERT INTO @EmployeeDutyHours
VALUES  ('2017-11-29 07:30:00.000', '2017-11-29 12:30:00.000'),
        ('2017-11-29 13:30:00.000', '2017-11-29 16:30:00.000')

INSERT INTO @EmployeeAttendanceHours 
VALUES  ('2017-11-29 07:27:24.000', '2017-11-29 09:44:33.000'),
        ('2017-11-29 11:57:37.000', '2017-11-29 12:05:39.000'),
        ('2017-11-29 15:12:31.000', '2017-11-29 17:24:32.000')

SELECT 
    FromTime = eah.InTime, 
    ToTime = eah.OutTime,
    Message = 'Inside Office'
FROM @EmployeeAttendanceHours eah

UNION

SELECT 
    FromTime = eah.OutTime,
    ToTime = eh.ToDateTime,
    Message = 'Outside Office'
FROM @EmployeeDutyHours eh,@EmployeeAttendanceHours eah 
WHERE eah.OutTime BETWEEN eh.FromDateTime AND eh.ToDateTime

UNION

SELECT 
    FromTime = eh.FromDateTime,
    ToTime = eah.InTime,
    Message = 'Outside Office'
FROM @EmployeeDutyHours eh, @EmployeeAttendanceHours eah
WHERE eah.InTime BETWEEN eh.FromDateTime AND eh.ToDateTime

ORDER BY 1, 2

我应该得到预期的结果?

**

  

修改

**

Below回答适用于上述情况而不适用于以下情况。

以下是员工的工作时间

案例#2

FromDateTime                ToDateTime
---------------------------------------------------
2017-11-29 07:30:00.000    2017-11-29 12:30:00.000
2017-11-29 13:30:00.000    2017-11-29 16:30:00.000

以下是员工的出勤时间(办公时间内)

InTime                          OutTime
--------------------------------------------------------
2017-11-29 07:27:24.000         2017-11-29 09:44:33.000
2017-11-29 11:57:37.000         2017-11-29 12:05:39.000
2017-11-29 15:12:31.000         2017-11-29 17:24:32.000

预期内外时间与工作时间的关系应低于:

FromTime                    ToTime                      Remarks
-----------------------------------------------------------------------
2017-11-29 07:27:24.000     2017-11-29 09:44:33.000     Inside Office
2017-11-29 09:44:33.000     2017-11-29 11:57:37.000     Outside Office
2017-11-29 11:57:37.000     2017-11-29 12:05:39.000     Inside Office
2017-11-29 12:05:39.000     2017-11-29 12:30:00.000     Outside Office
2017-11-29 13:30:00.000     2017-11-29 15:12:31.000     Outside Office
2017-11-29 15:12:31.000     2017-11-29 17:24:32.000     Inside Office

但是我在应用this回答后得到了结果:

FromTime                    ToTime                      Remarks
-----------------------------------------------------------------------
2017-11-29 07:27:24.000     2017-11-29 09:44:33.000     Inside Office
2017-11-29 07:30:00.000     2017-11-29 11:57:37.000     Outside Office
2017-11-29 09:44:33.000     2017-11-29 12:30:00.000     Outside Office
2017-11-29 11:57:37.000     2017-11-29 12:05:39.000     Inside Office
2017-11-29 12:05:39.000     2017-11-29 12:30:00.000     Outside Office
2017-11-29 13:30:00.000     2017-11-29 15:12:31.000     Outside Office
2017-11-29 15:12:31.000     2017-11-29 17:24:32.000     Inside Office

2 个答案:

答案 0 :(得分:0)

看看这个例子 - 我认为它解决了你想要完成的事情;但是,我不认为你的预期结果是完全准确的 - 我认为你错过了2017-12-11 07:30:00.000 - 2017-12-11 07:30:12.000的第一个“外部办公室”记录,因为员工技术上已经12秒钟了:

--DROP TABLE EmployeeDutyHours 
CREATE TABLE EmployeeDutyHours 
(
    EmployeeId BIGINT,
    ShiftFromTime DATETIME,
    ShiftToTime DATETIME
)

INSERT INTO dbo.EmployeeDutyHours
    VALUES  (1, '2017-12-11 07:30:00.000', '2017-12-11 12:30:00.000'),
            (1, '2017-12-11 15:30:00.000', '2017-12-11 18:30:00.000')

--DROP TABLE EmployeeAttendanceHours 
CREATE TABLE EmployeeAttendanceHours 
(
    EmployeeId BIGINT,
    InTime DATETIME,
    OutTime DATETIME
)

INSERT INTO dbo.EmployeeAttendanceHours 
    VALUES  (1, '2017-12-11 07:30:12.000', '2017-12-11 07:34:29.000'),
            (1, '2017-12-11 12:45:28.000', '2017-12-11 13:04:15.000'),
            (1, '2017-12-11 17:55:15.000', '2017-12-11 18:04:28.000')

SELECT 
    FromTime = eah.InTime, 
    ToTime = eah.OutTime,
    Message = 'Inside Office'
FROM EmployeeAttendanceHours eah

UNION

SELECT 
    FromTime = eah.OutTime,
    ToTime = eh.ShiftToTime,
    Message = 'Outside Office'
FROM dbo.EmployeeDutyHours eh
JOIN dbo.EmployeeAttendanceHours eah ON eah.EmployeeId = eh.EmployeeId
WHERE eah.OutTime BETWEEN eh.ShiftFromTime AND eh.ShiftToTime

UNION

SELECT 
    FromTime = eh.ShiftFromTime,
    ToTime = eah.InTime,
    Message = 'Outside Office'
FROM dbo.EmployeeDutyHours eh
JOIN dbo.EmployeeAttendanceHours eah ON eah.EmployeeId = eh.EmployeeId
WHERE eah.InTime BETWEEN eh.ShiftFromTime AND eh.ShiftToTime

ORDER BY 1, 2

答案 1 :(得分:0)

我希望以下查询适合您。

DECLARE @EmployeeDutyHours TABLE (
  FromDateTime datetime,
  ToDateTime datetime
)

DECLARE @EmployeeAttendanceHours TABLE (
  InTime datetime,
  OutTime datetime
)


--INSERT INTO @EmployeeDutyHours VALUES ('2017-12-11 07:30:00.000', '2017-12-11 12:30:00.000'),('2017-12-11 15:30:00.000', '2017-12-11 18:30:00.000')
--INSERT INTO @EmployeeAttendanceHours VALUES ('2017-12-11 07:30:12.000', '2017-12-11 07:34:29.000'), ('2017-12-11 12:45:28.000', '2017-12-11 13:04:15.000'), ('2017-12-11 17:55:15.000', '2017-12-11 18:04:28.000')

INSERT INTO @EmployeeDutyHours VALUES ('2017-11-29 07:30:00.000', '2017-11-29 12:30:00.000'), ('2017-11-29 13:30:00.000', '2017-11-29 16:30:00.000')
INSERT INTO @EmployeeAttendanceHours VALUES ('2017-11-29 07:27:24.000', '2017-11-29 09:44:33.000'), ('2017-11-29 11:57:37.000', '2017-11-29 12:05:39.000'), ('2017-11-29 15:12:31.000', '2017-11-29 17:24:32.000')


;WITH CTE
AS (SELECT
  *,
  LEAD(InTime, 1) OVER (ORDER BY InTime) AS NextIn,
  LEAD(OutTime, 1, '20491231') OVER (ORDER BY OutTime) AS NextOut,
  LAG(InTime, 1) OVER (ORDER BY InTime) AS PrevIn,
  LAG(OutTime, 1) OVER (ORDER BY OutTime) AS PrevOut
FROM @EmployeeAttendanceHours)


SELECT
  a.InTime,
  a.OutTime,
  'Inside Office' AS Remarks
FROM CTE a

UNION

SELECT
  a.OutTime,
  NextIn,
  'Outside Office'
FROM CTE a
CROSS APPLY (SELECT * FROM @EmployeeDutyHours WHERE (a.InTime < ToDateTime AND a.OutTime > FromDateTime) AND a.NextIn BETWEEN FromDateTime AND ToDateTime) d

UNION

SELECT
  a.OutTime,
  d.ToDateTime,
  'Outside Office'
FROM CTE a
CROSS APPLY (SELECT * FROM @EmployeeDutyHours WHERE a.OutTime BETWEEN FromDateTime AND ToDateTime AND a.OutTime < ToDateTime AND (a.NextOut > ToDateTime)) d

UNION

SELECT
  FromDateTime,
  a.InTime,
  'Outside Office'
FROM CTE a
CROSS APPLY (SELECT * FROM @EmployeeDutyHours WHERE a.InTime BETWEEN FromDateTime AND ToDateTime AND a.InTime > FromDateTime AND a.PrevOut NOT BETWEEN FromDateTime AND ToDateTime AND a.PrevIn IS NOT NULL) d

ORDER BY InTime, OutTime

评论案例#1并检查您的预期结果。

正如@ combatc2所说的那样,员工在#1的情况下技术上是12秒,如果你想要包含在结果中,请告诉我。

相关问题