我有一个SQL表,其中存储每个员工的进出时间戳。
有些员工不止一次地打卡(是因为他们没有听到卡片被读到),还有一些员工是因为某种原因而打卡的(也许他们会遇到朋友并保持交谈1到2分钟),他们需要等几分钟才能再次打卡才能进入转门。
示例SQL表数据如下(仅3名雇员):

现在,我想分类每一次,以了解什么是正确的时间戳,等等。
例如:

在您看到的EMP_01 (黄色记录)中,LAST_LEAVE在技术上是00:38:21,但是很明显,员工敲了两下,这就是真正的LAST_LEAVE是00:38:16的原因。
但是,EMP_04还有其他一些问题,如果你看到最后4张唱片,他连续3张,但这并不是因为他没有听到传感器发出的哔声,而是因为他从另一扇门离开时,谁知道是什么时候,但我们知道他在1小时后再次进入,等等。
那么,对如何处理这件事有什么建议吗?以及如何分配我的“状态”标志?
更新
例如,如果EMP_04有3个连续的相同类型的时间戳(IN's或OUT's):
我的容忍时间是120秒,所以第一次9:04:27是可以的,但是接下来的两个连续的时间戳应该是无效的,因为我的容忍度是120秒。
但是,例如,如果EMP_04具有以下连续时间戳:
那么唯一被标记为不活动的时间是上午9:04:35。因为上午9:04.35到9:08:10之间大于2分钟。
发布于 2014-04-30 15:34:21
首先,承认@RamRS将艰苦的工作放入触发器中,这里有一个经过测试,应该可以启动。显然,需要对拐角处的情况进行一些健壮的测试:
CREATE TRIGGER TS_FindDups ON dbo.TS FOR INSERT
AS
BEGIN
;WITH DupRecords
AS
(
SELECT i.EmployeeId, i.[TimeStamp]
FROM inserted i
INNER JOIN dbo.TS SRC ON i.EmployeeId = SRC.EmployeeId AND i.EntranceType = SRC.EntranceType
WHERE SRC.[Status] != 'Inactive'
/* same day (nice...thanks to RamRS) */
AND CAST(i.[TimeStamp] AS date) = CAST(SRC.[TimeStamp] AS date)
/* only checking newer timestamps (also need this so DATEDIFF <= 2 works correctly) */
AND i.[TimeStamp] > SRC.[TimeStamp]
/* newer timestamps are less than two minutes for same Employee, same day, same EntranceType */
AND DATEDIFF(MINUTE, SRC.[TimeStamp], i.[TimeStamp]) <= 2
)
UPDATE dbo.TS
SET [Status] = 'Inactive'
FROM dbo.TS SRC
INNER JOIN DupRecords ON SRC.EmployeeId = DupRecords.EmployeeId AND SRC.[TimeStamp] = DupRecords.[TimeStamp]
END发布于 2014-04-30 13:55:41
正如@mdisibio所述,我们可以使用触发器在插入行时添加“非活动”值来复制行。
这个触发器的大致草图如下:
CREATE TRIGGER trg_FindDups ON tbl_TimeStamp FOR INSERT
AS
BEGIN
DECLARE @CurrentMaxSwipeTime DATETIME
DECLARE @SwipeType
SELECT @SwipeType = EntranceType FROM INSERTED
IF (@SwipeType = 'O')
BEGIN
/* Employee is swiping OUT */
SELECT @CurrentMaxSwipeTime = MAX(T.TimeStamp) FROM tbl_TimeStamp T
WHERE T.EmployeeID = (SELECT EmployeeID FROM INSERTED) /* Same employee */
AND DATE(T.TimeStamp) = CAST(GETDATE() AS DATE) /* Same date */
AND DATEDIFF(minute,T.TimeStamp,GETDATE())<2 /* Within 2 minutes */
AND T.Status <> 'INACTIVE' /* of an active swipe */
AND T.EntraceType = 'O' /* Swiping out */
AND T.TimeStamp <> (SELECT TimeStamp FROM INSERTED) /* not the row we just inserted, H/T @mdisibio
IF @CurrentMaxSwipeTime IS NOT NULL
/* SET Status to INACTIVE */
UPDATE tbl_TimeStamp SET Status='INACTIVE' WHERE EmployeeID=(SELECT EmployeeID FROM INSERTED) AND TimeStamp=(SELECT TimeStamp FROM INSERTED)
END
ELSE
BEGIN
/* Employee is swiping in */
SELECT @CurrentMaxSwipeTime = MIN(T.TimeStamp) FROM tbl_TimeStamp T
WHERE T.EmployeeID = (SELECT EmployeeID FROM INSERTED) /* Same employee */
AND DATE(T.TimeStamp) = CAST(GETDATE() AS DATE) /* Same date */
AND DATEDIFF(minute,T.TimeStamp,GETDATE())<2 /* Within 2 minutes */
AND T.Status <> 'INACTIVE' /* of an active swipe */
AND T.EntraceType = 'I' /* Swiping in */
AND T.TimeStamp <> (SELECT TimeStamp FROM INSERTED) /* not the row we just inserted, H/T @mdisibio
IF @CurrentMaxSwipeTime IS NOT NULL
/* SET Status to INACTIVE */
UPDATE tbl_TimeStamp SET Status='INACTIVE' WHERE EmployeeID=(SELECT EmployeeID FROM INSERTED) AND TimeStamp=(SELECT TimeStamp FROM INSERTED)
END
END我在Server上工作已经有几年了,但我真的希望代码中没有错误。
--
干杯,
随机存取存储器
发布于 2014-04-30 15:46:56
让我快速总结一下你们的问题,然后一个接一个地提出:
假设:
所以..。在中间几分钟内复制记录。为了确定用户的状态,您必须查看他们的历史记录。我相信你的想法,有一个容忍几分钟是一个很好的想法,虽然这应该检查在输入和输出扫描。因为在你的内心里,你应该总是第一个。因为你应该一直吃最后一杯。
我想的是,每次插入/更新/删除特定员工的时间戳记录时,都会重新计算当天的所有状态。这样,如果有重复的扫描,您就不必担心在不同的行上来回调整状态。
您必须重新计算状态,如下所示:
https://stackoverflow.com/questions/23326277
复制相似问题