我当前正在编码现有的薪资系统,并且遇到以下问题。为了将他们转移到下一位,我需要计算一年中一名员工的休假天数。这些天可以是完整的日期,也可以是一天中的几个小时(例如,默认的8小时工作日为6小时假期)
但是,现有功能仅将上述数据存储在具有此类列的表中。
EmployeeID | StartDate | EndDate | Hours
1 01-02-2018 04-02-2018 24
1 08-03-2018 08-03-2018 4
2 30-12-2017 04-01-2018 48
3 30-12-2018 04-01-2019 48
现在的问题是我想将日期限制为仅上一年。因此,由于我们有2019年,所以我只需要从2018年开始放假。意味着具有不同开始和结束年份的记录,需要特殊处理
结果表应如下图所示
EmployeeID | HoursPreviousYear
1 28
2 32
3 16
我已经知道一些有用的SQL函数,例如DATEDIFF()或YEAR(),但是由于每条记录都是不同的,所以我可能需要使用游标并迭代表。然后将结果传递到另一个表,我将在查询中创建并返回它。
说实话,我感到困惑...
据我所见,我从来没有使用过游标,即使我可以返回一个表也不确定(我以后也需要在联接中使用它)。我不确定继续努力是否值得,但似乎应该有一种更简单的方法。
我的另一个选择是更改“保存”按钮的行为,以保存2条不同的记录,并且没有重叠的年份,但是我不能,因为我们有旧数据...
答案 0 :(得分:0)
显然,在某些极端情况下,这还不够彻底,但这应该可以帮助您入门。
假设每天休息8个小时,完全无法计算出周末或假日的日期范围,也不考虑某人休假,比如说休息三整天再休息半天。
DECLARE @Year int = 2018;
SELECT
EmployeeID,
SUM(CASE WHEN StartDate < DATEFROMPARTS(@Year,1,1)
THEN DATEDIFF(DAY,DATEFROMPARTS(@Year-1,12,31),EndDate)*8
WHEN EndDate > DATEFROMPARTS(@Year,12,31)
THEN DATEDIFF(DAY,StartDate,DATEFROMPARTS(@Year+1,1,1))*8
ELSE [Hours]
END) AS HoursPreviousYear
FROM
@table
GROUP BY
EmployeeID;
+------------+-------------------+
| EmployeeID | HoursPreviousYear |
+------------+-------------------+
| 1 | 28 |
| 2 | 32 |
| 3 | 16 |
+------------+-------------------+
答案 1 :(得分:0)
您可以使用DATEDIFF计算开始日期和结束日期的额外天数,以从总时数中减去额外的小时数,如以下查询所示-
SELECT EmployeeID,
SUM(Hours) - (SUM(StDiff)+SUM(EndDiff))*8 HoursPreviousYear
FROM
(
SELECT EmployeeID,
CONVERT(DATE, StartDate , 103) StartDate,
CONVERT(DATE, EndDate , 103) EndDate,
Hours,
CASE
WHEN YEAR(CONVERT(DATE, StartDate , 103)) = 2018 THEN 0
ELSE DATEDIFF(DD,CONVERT(DATE, StartDate , 103),CONVERT(DATE, '01-01-2018' , 103))
END StDiff,
CASE
WHEN YEAR(CONVERT(DATE, EndDate , 103)) = 2018 THEN 0
ELSE DATEDIFF(DD,CONVERT(DATE, '31-12-2018' , 103),CONVERT(DATE, EndDate , 103))
END EndDiff
FROM your_table
WHERE YEAR(CONVERT(DATE, StartDate , 103)) <= 2018
AND YEAR(CONVERT(DATE, EndDate , 103)) >= 2018
)A
GROUP BY EmployeeID