DCN*_*YAM 5 sql sql-server-2005
我们有一个表格如下:
|ID|EmployeeID|Date |Category |Hours|
|1 |1 |1/1/2010 |Vacation Earned|2.0 |
|2 |2 |2/12/2010|Vacation Earned|3.0 |
|3 |1 |2/4/2010 |Vacation Used |1.0 |
|4 |2 |5/18/2010|Vacation Earned|2.0 |
|5 |2 |7/23/2010|Vacation Used |4.0 |
Run Code Online (Sandbox Code Playgroud)
业务规则是:
我们需要返回Vacation Earned的行,这些行没有被使用的假期抵消.如果使用的假期仅抵消了度假获得记录的一部分,我们需要返回显示差异的记录.例如,使用上表,结果集如下所示:
|ID|EmployeeID|Date |Category |Hours|
|1 |1 |1/1/2010 |Vacation Earned|1.0 |
|4 |2 |5/18/2010|Vacation Earned|1.0 |
Run Code Online (Sandbox Code Playgroud)
请注意,记录2被删除,因为它被使用时间完全抵消,但记录1和4仅部分使用,因此它们被计算并返回.
我们想到的唯一方法是将所有度假获得的记录放在临时表中.然后,获取使用的总休假并循环通过临时表,删除最旧的记录并从使用的总休假中减去该值,直到使用的总假期为零.我们可以清理它,因为剩下的假期只是最古老的度假记录的一部分.这将使我们留下优秀的度假收入记录.
这有效,但效率很低,表现不佳.此外,随着越来越多的记录被添加,性能将随着时间的推移而降低.
对于更好的解决方案有什么建议吗?如果没有,我们只需要这样做.
编辑:这是供应商数据库.我们无法以任何方式修改表结构.
下面应该这样做..
(但正如其他人提到的,最好的解决方案是调整剩余假期的使用情况..)
select
id, employeeid, date, category,
case
when earned_so_far + hours - total_spent > hours then
hours
else
earned_so_far + hours - total_spent
end as hours
from
(
select
id, employeeid, date, category, hours,
(
select
isnull(sum(hours),0)
from
vacations
WHERE
category = 'Vacation Earned'
and
date < v.date
and
employeeid = v.employeeid
) as earned_so_far,
(
select
isnull(sum(hours),0)
from
vacations
where
category = 'Vacation Used'
and
employeeid = v.employeeid
) as total_spent
from
vacations V
where category = 'Vacation Earned'
) earned
where
earned_so_far + hours > total_spent
Run Code Online (Sandbox Code Playgroud)
逻辑是
earned获得的小时数