我正致力于实施用于监控绩效的积分跟踪系统。员工的目标是根据需要提供少量积分。有一个积分系统,允许员工通过在不同时间段内表现更好来减少积分。在30天的表现中,积分最多减少1分,如果没有发生事故则减少60分,如果没有事故则减少到90分。它们不能累积负值,并且点从最旧的日期到最新的日期滚动。下面的示例表是已导入SQL Server 2012数据库的现有表的表示形式。
Employee Points Date Previous Note
Smith, Joe 0.25 3/21/2013
Smith, Joe 1 4/1/2013
Smith, Joe 0.25 5/6/2013
Smith, Joe 0.5 5/8/2013
Smith, Joe 1 7/10/2013
Jones, Tom 1 4/10/2013
Jones, Tom 1 4/18/2013
Jones, Tom 0.5 4/22/2013
Jones, Tom 2 6/25/2013
Jones, Tom 0.25 7/26/2013
Jones, Tom 0.25 7/28/2013
由于动态使用数据,转到多个来源(如C#,Excel,Email),因此需要构建确定性函数并生成更新的表或视图,以显示类似于以下内容的内容。下面的例子将是报告在2013年5月18日提取的报告。每个员工都会得到1分。因为Joe的第一个点是.25,它将被设置为0,下一个点1.00将被剩余的0.75减少到0.25的值。因为汤姆有一个满分作为他的第一个点,它将从1分中减去,导致该日期为0分。在更新Point值之前,该函数还应标记Points Column的先前值。该函数应该提供关于更改点的原因的注释,注释字段中的日期会很好,但是NoteDate的单独Column可以包含日期。该函数可以在INSERT / UPDATE触发器上运行,因为每日使用率非常低。它应该检查当前日期与最后一个点日期。
Employee Points Date Previous Note
Smith, Joe 0.00 3/21/2013 0.25 Rolled Off by System - 30 Day Policy 05/01/2013
Smith, Joe 0.25 4/1/2013 1.00 Rolled Off by System - 30 Day Policy 05/01/2013
Smith, Joe 0.25 5/6/2013
Smith, Joe 0.50 5/8/2013
Jones, Tom 0.00 4/10/2013 1.00 Rolled Off by System - 30 Day Policy 05/22/2013
Jones, Tom 1.00 4/18/2013
Jones, Tom 0.50 4/22/2013
截至今天的2013年8月24日,结果应反映以下内容。乔总共得到0分,而汤姆总共得到2分,到第28分只得到1分。大约有2,000条记录,因此很难手动更改这些记录。根据该系统的性质及其实现,可以运行1个脚本来协调当前记录,并有一个单独的脚本来管理正在进行的条目。
Employee Points Date Previous Note
Smith, Joe 0.00 3/21/2013 0.25 Rolled Off by System - 30 Day Policy 05/01/2013
Smith, Joe 0.00 4/1/2013 0.25 Rolled Off by System - 30 Day Policy 06/07/2013
Smith, Joe 0.00 5/6/2013 0.25 Rolled Off by System - 30 Day Policy 06/07/2013
Smith, Joe 0.00 5/8/2013 0.50 Rolled Off by System - 30 Day Policy 06/07/2013
Smith, Joe 0.00 7/10/2013 1.00 Rolled Off by System - 30 Day Policy 08/10/2013
Jones, Tom 0.00 4/10/2013 1.00 Rolled Off by System - 30 Day Policy 05/22/2013
Jones, Tom 0.00 4/18/2013 1.00 Rolled Off by System - 60 Day Policy 06/21/2013
Jones, Tom 0.00 4/22/2013 0.50 Rolled Off by System - 30 Day Policy 07/25/2013
Jones, Tom 1.50 6/25/2013 2.00 Rolled Off by System - 30 Day Policy 07/25/2013
Jones, Tom 0.25 7/26/2013
Jones, Tom 0.25 7/28/2013
我开始在EmployeePerformance TABLE上使用以下内容,以创建一个视图,以显示每个员工的每个记录与其ID之间的天数。然后我使用DENSE_RANK()为每位员工编号,并提供出勤视图中的所有信息。我最初的想法是使用递增的VARIABLE为每个员工循环一个WHILE循环,然后检查DATE_DIFFERENCE以查看是否有任何大于30的值。如果不是,我计划将该员工的所有记录插入到最终表中,并从Attend2表中删除它们。比我想象的更多的脚本是必要的。我反而想过使用CURSOR来创建一次性传递,然后再调用另一个函数。我对CURSOR的经验不多。
CREATE VIEW Attendance AS
SELECT A.ID, A.FullName, A.EmployeeID, A.AttendanceDate, A.OccurrenceAmount, A.Comments, A.RecordCreatedDate, A.RecordCreatedUser, (DATEDIFF(DAY, A.AttendanceDate, B.AttendanceDate))*-1 AS DATE_DIFFERENCE
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY AttendanceDate) AS Row_Num, *
FROM dbo.EmployeePerformance) AS A
LEFT JOIN (
SELECT ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY AttendanceDate) AS Row_Num, *
FROM dbo.EmployeePerformance) AS B
ON A.EmployeeID=B.EmployeeID AND A.Row_Num=B.Row_Num+1
SELECT *, DENSE_RANK() OVER (ORDER BY Attendance.EmployeeID) AS Row_Num
INTO dbo.Attend2
FROM dbo.Attendance
我有一些想法可以解决这个问题,但我希望有人可能遇到过类似情况,或者曾经遇到类似这样的问题。我宁愿把它构建成一个我可以触发的简洁代码片段,并且在低容量环境中使用SQL数据库我不是非常担心性能,但是我想找到一个能够保持性能的良好解决方案心神。感谢您提供的任何帮助或反馈。
答案 0 :(得分:1)
我不确定我是否完全遵循您的方法/期望的结果,但对于初学者,您可以使用LEAD
代替JOIN
/ ROW_NUMBER()
来获取DATEDIFF
:
SELECT ID
, FullName
, EmployeeID
, AttendanceDate
, OccurrenceAmount
, Comments
, RecordCreatedDate
, RecordCreatedUser
, DATEDIFF(DAY, AttendanceDate, LEAD(AttendanceDate) OVER(PARTITION BY EmployeeID ORDER BY AttendanceDate))*-1 AS DATE_DIFFERENCE
FROM dbo.EmployeePerformance)