我有一个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)
例如,某些Employee有两个enter和两个退出事件,它完美无缺。但是,如果有一个退出和两个输入事件,它就不会像我想要的那样工作。
示例:员工XXX于05:44开始工作,然后他于06:28退出。后来他在06:50回来,并在12:33再次退出。此过程应返回@worktime
等于387分钟。
第二天他犯了一个错误,他在06:00来上班,但在EVENTS
表中,有两个相同的记录。他在14:00退出(exit
表中只有1 EVENT
个记录。程序返回960分钟。如果它返回480,我想。
如果输入事件的数量不等于退出事件的数量(例如:2进入和1退出),如何修复交叉申请?
图片示例:
下面的例子很完美。
选定的行(1,4,5,8)被传递给程序。 ControlPointId = 6
是入口点,ControlPointId = 3
是退出点。 EventTypeId = 1
是输入事件,EventTypeId = 2
是退出。
但这不起作用:
在这种情况下,ControlPointId = 64
是入口点,ControlPointId = 56
是出口点。我们可以看到,这个Employee
犯了错误,ControlPoint
读了两次卡片,所以有两个入场事件和一个退出事件。
我应该如何更改程序?当出现像这样的错误时(或者在相反的情况下:1个条目和2个退出事件),它应该只进行第一次进入事件。
答案 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)