我正在我工作的地方编写一份报告,该报告将帮助我们的行政部门计算假期应计金额。
如果您连续工作 40 小时,在第 5 年开始时,您会累积 10 小时,在第 10 年开始时,您会累积 12 小时。如果您最后休息一下,或者您工作了 40 小时,那么下降到 20,然后你的时间重置,直到你再次达到 40。
在我的数据库中,我有一个“工作进展”字段,它给出了“员工 ID”、职位的开始日期和结束日期。如果他们当前受雇,则结束日期为 NULL
。
这些是我正在使用的数据库中的一些字段:
+-----+-------+------------+------------+-------+
| ID | EmpID | startdate | enddate | hours |
+-----+-------+------------+------------+-------+
| 1 | 1 | 2011-06-01 | NULL | 40 |
| 2 | 2 | 2011-10-10 | NULL | 40 |
| 3 | 3 | 2000-03-01 | NULL | 40 |
| 5 | 5 | 1999-06-07 | NULL | 40 |
| 6 | 6 | 2012-05-16 | NULL | 40 |
| 7 | 7 | 1996-09-25 | NULL | 40 |
| 8 | 8 | 2015-10-07 | NULL | 40
| 9 | 8 | 2012-10-17 | 2015-10-06 | 40 |
| 12 | 9 | 2000-06-05 | NULL | 40 |
| 16 | 12 | 2005-08-04 | NULL | 40 |
| 17 | 13 | 2008-01-20 | NULL | 40 |
| 19 | 14 | 1999-02-17 | 2001-05-31 | 40 |
| 22 | 16 | 2016-04-01 | NULL | 40 |
| 23 | 16 | 1999-11-01 | 2016-03-31 | 40 |
| 29 | 18 | 1997-08-01 | NULL | 40 |
| 31 | 19 | 2012-02-13 | NULL | 40 |
| 36 | 22 | 2006-04-05 | NULL | 40 |
| 38 | 23 | 2015-07-01 | 2016-03-12 | 40 |
| 44 | 27 | 2016-03-07 | 2017-03-03 | 40 |
| 46 | 28 | 2002-11-11 | NULL | 40 |
| 47 | 29 | 2016-04-11 | NULL | 40 |
所以我需要一个查询来查看用户 (EmpID
) 上一个连续的完整时间(40 小时),然后检查它已经多少年了。
这是否有意义或可能?我见过很多例子,他们用单个日期来做,但没有一个用日期范围。
在计算这个字段时,我必须确保只包括最近的连续时间 40 小时。考虑这个例子:
一名员工从 2016 年 1 月 1 日到 2016 年 10 月 1 日每周工作 40 小时,因此他们有 9 个月的全职时间。然后他们从 2016 年 10 月 2 日到 2017 年 1 月 1 日转为兼职。然后在这段时间之后,他们从 2017 年 1 月 2 日到 2017 年 2 月 1 日回到全职,然后被提升到另一个部门,从 2017 年 2 月 1 日到今天仍然是全职。
我们要做的是忽略他们从 2016 年 1 月 1 日到 2016 年 10 月 1 日的工作时间,因为当他们去兼职时,他们失去了应计收入。现在他们从 2017 年 1 月 2 日到现在又开始了,我们确实必须将这些包括在计算中。
所以表格看起来像这样:
+-----+-------+------------+------------+-------+--------+
| ID | EmpID | startdate | enddate | hours | Title |
+-----+-------+------------+------------+-------+--------+
| 1 | 1 | 2016-01-01 | 2016-10-01 | 40 | Job A |
| 2 | 1 | 2016-10-02 | 2017-01-01 | 20 | Job B |
| 3 | 1 | 2017-01-01 | 2017-02-01 | 40 | Job C |
| 4 | 1 | 2017-02-02 | NULL | 40 | Job D |
+-----+-------+------------+------------+-------+--------+
所以由于ID 1在ID 2处有断点,并不会计算在并发时间,所以MySQL只能考虑ID 3 & 4记录的时间。
那么输出可能就像“EmpID - Diff Years”一样简单。 - 所以上面的示例正确输出应该是 1 - 0.8082 年
最佳答案
Demo (可能需要单击运行 (F8) 才能看到更新。)
我仍然不知道您到底在追求什么……每个员工的应计率?连续 40 小时服务的年数取决于我们如何处理年份,以及日期差异的总和是否适用于闰年等等......
SELECT EMPID
, case when sum(yearsDiff) >= 5 and sum(yearsDiff) < 10 then 10
when sum(yearsDiff) >= 10 then 12 end as AccrualRate
, sum(yearsDiff) as CurrentConsecutive40HrYears
FROM (SELECT A.*
, datediff(coalesce(endDate,curDate()),StartDate)/365 as YearsDiff
FROM so46896406 A
LEFT JOIN (SELECT max(endDate) AccStart, EmpID
FROM SO46896406
WHERE Hours < 40
GROUP BY EmpID) B
on A.EmpID = B.EmpID
WHERE A.StartDate>=coalesce(B.AccStart,A.StartDate)
)SUB
GROUP BY EmpID;
我使用 suquery 查找员工的工作的最大日期 < 40 小时。然后我将其用作最早可能的连续 40 小时范围。然后,我们使用日期差异对员工的所有条目求和,以查看总范围是否 > 5 年且 < 10,并将 10 指定为比率。如果 > 10,则速率为 12。任何低于 5 的比率都是 NULL。
我使用您的新数据添加了 empID 30,因为我不想重复原始集中的 1。它像你一样以 .8082 的形式出现。这导致应计率为空,因为应计率为 10 需要 < 5 年。
coalesce(b.AccStart,A.StartDate) 只是说保留所有开始日期大于最大非 40 小时日期的记录;但如果员工从未有过 40 小时的约会;只需返回该员工的所有记录。
现在我们可以将 where 子句简化为:
WHERE B.AccStart is null OR A.StartDate >=B.AccStart;
因为我们只需要工作时间从未少于 40 岁的员工的记录;或那些工作较少的人;但我们只想要他们在日期之后的记录少于 40。
这两个记录都获得相同的结果;但是 WHERE A.StartDate>=coalesce(B.AccStart,A.StartDate)
应该更有效,因为它避免了由于 or 而对 A.StartDate 进行双索引搜索。
关于mysql - 具有特定凭据的连续天数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46896406/