Sql 根据期间规则动态获取假日期间
每个员工都有假期政策。这项假期政策让我知道以下几点: 根据工作年限的不同,假期可能会有所变化 根据工作年数,每个周期允许的最大天数是多少 例如: 该员工于2011年10月10日加入公司 第一个工作年度2012年10月10日,员工有6天假期可供使用。但仅在第一年,该日期必须在2012年10月10日至2012年12月31日期间使用 因此,规则是: 1个工作年度-期间开始:员工加入日期:当年的JODA至年底。 对于接下来的所有年份,规则为:>1个工作年-期初:1/1/年至12/31/年。 此规则位于具有以下架构的表中: 0年是指所有年份 我对startperiod和endperiod列使用了varchar4数据类型 下表列出了每个工作年允许的最大天数: 所以我需要的结果是这样的: 第一行,期间根据工作年=1的规则开始,其余行的期间从一年的第一天开始,到一年的最后一天结束 我已经用相同的列和数据创建了一个SQL FIDLE 我的问题是,我不知道如何在不使用光标的情况下在一次选择中获得所有时段Sql 根据期间规则动态获取假日期间,sql,sql-server,Sql,Sql Server,每个员工都有假期政策。这项假期政策让我知道以下几点: 根据工作年限的不同,假期可能会有所变化 根据工作年数,每个周期允许的最大天数是多少 例如: 该员工于2011年10月10日加入公司 第一个工作年度2012年10月10日,员工有6天假期可供使用。但仅在第一年,该日期必须在2012年10月10日至2012年12月31日期间使用 因此,规则是: 1个工作年度-期间开始:员工加入日期:当年的JODA至年底。 对于接下来的所有年份,规则为:>1个工作年-期初:1/1/年至12/31/年。 此规则位于具
我很感激任何关于如何做的帮助和建议。这似乎不是一项简单的任务。从加入一个数字表开始,这样每个员工每年都可以得到一行
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
现在,您可以轻松地应用您的逻辑,因为您有年份编号,您可以计算年初,并根据需要进行比较,依此类推。使用ISNULLwyd.alloweddays、wyd0.alloweddays允许您的“默认值”。您可以按以下方式尝试在单个查询中获得所需的输出
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
这是一个数据模型的示例,它将冗余降至最低,而不利于复杂性。尽管如此,我们并不总能改变数据模型 下面是您问题的解决方案,它使用封装在函数中的CTE生成必要的表格数据 我注意到我对需求的理解不同,你和其他人实现了它。如果结果证明我错了,那么这会给你你描述的结果
您的SQL FIDLE中有一个错误:您在1年级和0年级都使用了JODA。您应该能够使用workingyear_days表作为查询的主表来实现所需的结果,以便每年获得一行,并根据其他列的需要连接到其他表。我只是修复了SQL FIDLE。您是对的。dbo.nums意味着什么?一个数字表。如:创建表dbo.nums num int主键;插入dbo.nums通过从sys.all_列中选择1在订单上选择行_编号;
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