根据期间规则动态获取假期

时间:2014-08-11 19:45:47

标签: sql sql-server

每位员工都有假期政策。这个假期政策让我知道以下内容:

  • 根据工作年数,假期可能会改变

  • 取决于工作年数,是每个时段允许的最大天数

所以,例如:

  • 该员工于10/10/2011加入公司

  • 第一个工作年(10/10/2012)该员工有6个假期。但是,从今日起的第一年必须在2012年10月10日至2012年12月31日期间使用。

所以规则是:

  • 1个工作年度 - 期间开始:当年的员工JoinDate( JODA )到年底。
  • 在接下来的几年里,规则是:> 1个工作年度 - 期间开始:1/1 /年到12/31 /年。

此规则位于包含以下架构的表中:

enter image description here

0年意味着所有年份

我为varchar(4)startperiod列使用endperiod数据类型

每个工作年的最大允许天数如下表所示:

enter image description here

所以我需要的结果是这样的:

enter image description here

第一行,期间根据规则(工作年份= 1)开始,对于其余行,期间从一年的第一天开始,到一年的最后一天结束。

我创建了一个具有相同列和数据的SQL小提琴。

http://sqlfiddle.com/#!6/29681

我的问题是我无法弄清楚如何使用SELECTCURSOR 中使用{{1}}获取所有句点。

我感谢您提供有关如何操作的任何帮助和建议。似乎不是一项简单的任务。

3 个答案:

答案 0 :(得分:0)

首先加入一个数字表,以便每位员工每年获得一行。

SELECT * --change this
FROM dbo.hd_employee e
JOIN 
dbo.nums n 
   ON n.num <= datediff(year, hd.joindate, getdate()) + 1
LEFT JOIN dbo.hd_workingyear_days wyd
    ON wyd.year = n.num
LEFT JOIN dbo.hd_workingyear_days wyd0
    ON wyd.year IS NULL
    AND wyd0.year = 0

现在您可以轻松应用逻辑,因为您有年份编号,您可以计算年份的开始,并根据需要进行比较,依此类推。使用ISNULL(wyd.alloweddays, wyd0.alloweddays)允许您的默认&#39;。

答案 1 :(得分:0)

您可以尝试以下方式在单个查询中获得所需的输出...

Select 
subqry2.employeeid,
Subqry2.startdt,
Subqry2.enddt,
Subqry2.workingYears,
Subqry2.alloweddays,
Subqry2.daysused,
(Subqry2.alloweddays-Subqry2.daysused) as remaining
from
(
select 
subqry1.employeeid,
subqry1.startdt,
subqry1.enddt,
subqry1.workingYears,
subqry1.alloweddays,
(select COUNT(1) from 
   hd_employee_holiday subqry 
   where subqry.employeeid = subqry1.employeeid 
   and subqry.date between subqry1.startdt and subqry1.enddt 
) as daysUsed
from
(
select 
Q1.employeeid,
 -- without using the rule table
 -- Case when Q2.number <= 1 then dateadd(yy,Q2.number,Q1.joindate) else dateadd(yy, datediff(yy,0,dateadd(yy,q2.number,q1.joindate)),0) end StartDt,
 -- DATEADD(yy, DATEDIFF(yy,0,dateadd(yy,q2.number+1,q1.joindate) + 1), -1) EndDt,
 -- using rule table
(select case when startperiod='JODA' then dateadd(yy,q2.number,Q1.joindate) 
         else dateadd(yy,Q2.number,cast(cast(year(Q1.joindate) as varchar) + startperiod as DATE)) end 
 from hd_workingyear_rule Q5 where Q5.year = (case when Q2.number != 1 then 0 else Q2.number end) 
) StartDt,
(select dateadd(yy,Q2.number,cast(cast(year(Q1.joindate) as varchar) + endperiod as DATE)) 
 from hd_workingyear_rule Q5 where Q5.year = (case when Q2.number != 1 then 0 else Q2.number end) 
) EndDt,
Q2.number WorkingYears,
Q3.alloweddays,
Q1.years,
Q2.number 
from
(select employeeid,joindate,datediff(year,joindate,getdate())+1 as years  from hd_employee) Q1
join master..spt_values Q2 on Q2.type = 'P' and Q2.number < Q1.years
join hd_workingyear_days Q3 on (Q2.number) = Q3.year
) subqry1
) Subqry2

使用输入表和数据输出上述查询如下

empid   startdt     enddt   WY  DA  DU  DR
1   2012-10-10  2012-12-31  1   6   3   3
1   2013-01-01  2013-12-31  2   8   2   6
1   2014-01-01  2014-12-31  3   9   4   5

答案 2 :(得分:0)

这是一个数据模型的示例,它可以最大限度地减少冗余,从而降低复杂性。话虽如此,我们并不总是能够改变数据模型。

以下是您的问题的解决方案,它使用函数中包含的CTE生成必要的表格数据。

SQL Fiddle Solution

我注意到我以不同的方式阅读了您和其他人实施的要求。如果事实证明我错了,那么这将为您提供所描述的结果。

SQL Fiddle Alternate Solution