我有一个SQL表,我将每个员工存储在IN和OUT时间戳中。
有些员工不止一次打卡(因为他们没有听到卡被读取),其他员工因某种原因打卡(也许他们遇到了朋友和他们会等待几分钟,然后再次打开进入旋转栅门。
示例SQL表数据如下所示(仅限3名员工):
现在,我想每次分类以了解时间戳是否正确等等。
例如:
在你看到 EMP_01 (黄色记录)时,LAST_LEAVE技术上是00:38:21,但很明显,员工打了两次就是为什么真正的LAST_LEAVE是00:38:16。
但是,EMP_04有一些其他问题,如果你看到最后4个记录,他连续3个IN,但那些不是因为他没有听到传感器的嘟嘟声,那是因为他从其他门离开没有打击谁知道什么时候,但我们知道他再次进入1小时,依此类推。
那么,关于如何处理这个的任何建议?以及如何分配我的“状态”标志?
更新:
如果EMP_04有3个相同类型的连续时间戳(IN或OUT),例如:
我的容忍度在120秒之间,所以第一次9:04:27就可以,但接下来的2个连续时间戳应该是不活动的,因为我的容差是120秒。
但是,例如,如果EMP_04具有以下连续时间戳:
然后标记为非活动的唯一时间将是上午9:04:35。因为在9:04.35和9:08:10之间大于2分钟。
答案 0 :(得分:2)
首先,承认@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
答案 1 :(得分:1)
就像@mdisibio所述,我们可以使用触发器来添加值&#34; INACTIVE&#34;在插入行时复制行。
这个触发器的草图将是:
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
自从我使用SQL Server以来已经有几年了,但我真的希望代码中没有错误。
-
干杯,
拉姆
答案 2 :(得分:0)
让我快速总结一下你的问题并逐一介绍:
假设:
所以... 在两者之间重复记录几分钟。为了确定用户的状态,您必须查看他们的历史记录。我相信你有一个几分钟的容差的想法是一个很好的,虽然这应该在IN和OUT扫描检查。对于IN,你应该总是拿第一个。对于OUT,你应该总是拿最后一个。
我想的是,每当您为特定日期插入/更新/删除特定员工的时间戳记录时,您都会重新计算当天的所有状态。这样,如果有重复扫描,您就不必担心在不同的行上向后和向前移动状态。
您必须重新计算以下状态: