SQL-计算日期段中一年内的相对金额

时间:2019-06-19 17:13:02

标签: sql sql-server dynamic-sql

我当前正在编码现有的薪资系统,并且遇到以下问题。为了将他们转移到下一位,我需要计算一年中一名员工的休假天数。这些天可以是完整的日期,也可以是一天中的几个小时(例如,默认的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条不同的记录,并且没有重叠的年份,但是我不能,因为我们有旧数据...

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