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

问题描述 投票:1回答:2

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

以下是员工的工作时间

情况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
sql sql-server sql-server-2012
2个回答
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秒,如果你想要包含在结果中,请告诉我。


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
© www.soinside.com 2019 - 2024. All rights reserved.