连续日计数具有特定凭据

时间:2017-10-23 18:46:38

标签: mysql

我正在制作一份报告,我的工作将有助于我们的政府计算出假期应计。

如果你连续工作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年

2 个答案:

答案 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 希望它有所帮助!