2017-08-29 26 views
3

我有一个包含进入和退出事件的EVENT表。我计算工作时间与步骤:当记录重复时修复交叉应用行

SET @worktime = (SELECT SUM(mins) 
       FROM 
        (SELECT 
          entry.EmployeeId, entry.DateTime AS EntryDateTime, 
          [exit].DateTime AS ExitDateTime, DATEDIFF(MINUTE, entry.DateTime, [exit].DateTime) AS mins 
         FROM 
          Events entry 
         CROSS APPLY 
          (SELECT TOP 1 e.DateTime 
          FROM Events e 
          WHERE e.EmployeeId = entry.EmployeeId 
          AND e.DateTime > entry.DateTime 
          AND e.EventTypeID = 2 
          AND CAST(e.DateTime AS DATE) = CAST(@data AS DATE) 
          AND e.ControlPointID IN (SELECT ControlPointID 
                 FROM ControlPoints 
                 INNER JOIN dbo.Split(RIGHT(@rcp, LEN(@rcp) - 2), ';') AS split ON ControlPoints.NAme = split.Data + ' EXIT') 
          ORDER BY e.DateTime ASC) AS [exit] 
         WHERE 
          entry.EventTypeId = 1 
          AND EmployeeId = @code 
          AND CAST(entry.DateTime AS DATE) = CAST(@data AS DATE) 
          AND ControlPointID IN (SELECT ControlPointID 
               FROM ControlPoints 
               INNER JOIN dbo.Split(RIGHT(@rcp, LEN(@rcp) - 2), ';') AS split ON ControlPoints.NAme = split.Data + ' ENTRY') 
                               AND CAST(entry.[DateTime] AS DATE) = CAST(@data AS DATE)) AS input 
       GROUP BY EmployeeId) 

例如,如果有两个输入和一些员工两个出口的事件,它可以完美运行。但是,如果有一个退出和两个输入事件,它不会像我想工作一样。

示例:员工XXX在05:44工作,然后他在06:28退出。之后他在06:50回来,并在12:33再次退出。此过程应返回@worktime等于387分钟。

第二天他犯了一个错误,他在06:00工作,但在EVENTS表中有两个相同的记录。他在14:00退出(只有exit记录在EVENT表中)。程序返回960分钟。我想,如果它返回480.

当输入事件数量不等于退出事件数量(例如:2进入和1退出)时,如何修复交叉应用?

带图像的例子:

下面的例子很完美。

Working Example

选定行(1,4,5,8)被传递给程序。 ControlPointId = 6是入口点,ControlPointId = 3是退出点。 EventTypeId = 1是输入事件,EventTypeId = 2是退出。

但是,这并不工作:

Not Working

在这种情况下,ControlPointId = 64的入口点和ControlPointId = 56是出口点。我们可以看到,这个Employee出错了,ControlPoint两次读了他的卡片,所以有2个入口事件和1个出口事件。

我该如何更改程序?当出现像这样的错误时(或者相反的情况:1入口和2出口事件),它应该只进入第一个入口事件。

+3

任何方式,我们可以得到的架构和一些数据来看看,并帮助找出其中的问题可能是。 – ttallierchio

+0

@ttallierchio请参阅编辑 – fanarek

+0

尝试对入口和出口进行排名,然后分别使用第一个入口和出口。 –

回答

1

你可以试试这个。如果不同的入口事件具有相同的退出事件,我把第一个条目使用ROW_NUMBER

SET @worktime = (SELECT SUM(mins) 
       FROM 
        (SELECT 
          entry.EmployeeId, entry.DateTime AS EntryDateTime, 
          [exit].DateTime AS ExitDateTime, 
          DATEDIFF(MINUTE, entry.DateTime, [exit].DateTime) AS mins, 
          RN = ROW_NUMBER() OVER (PARTITION BY [exit].EventID ORDER BY entry.DateTime) 
         FROM 
          Events entry 
         CROSS APPLY 
          (SELECT TOP 1 e.DateTime, e.EventID 
          FROM Events e 
          WHERE e.EmployeeId = entry.EmployeeId 
          AND e.DateTime > entry.DateTime 
          AND e.EventTypeID = 2 
          AND CAST(e.DateTime AS DATE) = CAST(@data AS DATE) 
          AND e.ControlPointID IN (SELECT ControlPointID 
                 FROM ControlPoints 
                 INNER JOIN dbo.Split(RIGHT(@rcp, LEN(@rcp) - 2), ';') AS split ON ControlPoints.NAme = split.Data + ' EXIT') 
          ORDER BY e.DateTime ASC) AS [exit] 
         WHERE 
          entry.EventTypeId = 1 
          AND EmployeeId = @code 
          AND CAST(entry.DateTime AS DATE) = CAST(@data AS DATE) 
          AND ControlPointID IN (SELECT ControlPointID 
               FROM ControlPoints 
               INNER JOIN dbo.Split(RIGHT(@rcp, LEN(@rcp) - 2), ';') AS split ON ControlPoints.NAme = split.Data + ' ENTRY') 
                               AND CAST(entry.[DateTime] AS DATE) = CAST(@data AS DATE)) AS input 
       WHERE RN = 1 
       GROUP BY EmployeeId) 
+0

它的工作原理。完美!谢谢。 – fanarek

+0

不客气! –