我正在制作一份报告,我的工作将有助于我们的政府计算出假期应计。
如果你连续工作40个小时,在你的第5年开始时,你会得到10小时的累积,而在你的第10个月开始时,你会得到12个。如果你最终休息,或者你工作了40个小时,那么下降到20,然后你的时间重置,直到你再次达到40。
在我的数据库中,我有一个" Job Progression"它给出了"员工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年2月10日至2017年1月1日搬到兼职。然后在这段时间之后,他们会回到2017年2月1日至2017年1月1日至2017年的全职工作,然后转到另一个部门,从2017年2月1日到今天仍然全职。
我们要做的就是忽略他们从2016年1月1日到2016年10月1日的工作时间,因为他们去兼职时失去了应计。现在它们从2017年1月1日起再次开始,我们必须将它们包含在计算中。
所以表格看起来像这样:
+-----+-------+------------+------------+-------+--------+
| 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年
答案 0 :(得分:1)
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来查找作业的最大日期&lt;员工40个小时。然后我用它作为最早可能的连续40小时范围。然后,我们使用日期差异对员工的所有条目求和,以查看总范围是否> 5年和&lt; 10并指定10作为费率。如果&gt; 10,然后12是率。低于5的任何东西都是空率。
我使用您的新数据添加了empID 30,因为我不想在原始集中重复1。它像你一样以.8082出现。这导致应计利率为零,因为它是&lt; 5年需要累计10。
coalesce(b.AccStart,A.StartDate)简单地说保留所有开头日期为&gt;的记录。最长非40小时的日期;但如果一名员工从未有过40小时的约会;只需返回该员工的所有记录。
现在我们可以将where子句简化为:
WHERE B.AccStart is null OR A.StartDate >=B.AccStart;
因为我们只想要从未工作过少于40岁的就业者的记录;或那些工作较少的人;但我们只希望他们的记录在日期少于40之后。
这两个记录都达到了相同的结果;但WHERE A.StartDate>=coalesce(B.AccStart,A.StartDate)
应该更有效率,因为它避免了A.StartDate上的双索引搜索,因为或。
答案 1 :(得分:0)
以下查询应该有效。
select EmpID,
case when enddate is null then (DAY(now()) - DAY(startdate))/365
else (DAY(enddate) - DAY(startdate))/365
end as diff_years
from yourTable
where hours=40
group by EmpId
having max(startdate);
Click here for Demo 希望它有所帮助!