SQL - рассчитать относительные суммы в течение года по сегментам даты - PullRequest
0 голосов
/ 19 июня 2019

Я в настоящее время кодирую существующую систему начисления заработной платы, и у меня есть проблема ниже.Мне нужно сосчитать количество отпусков одного работника за один год, чтобы перевести их на следующий.Дни могут быть либо полными, либо часами в дне (например, 6-часовой отпуск по умолчанию из 8-часового рабочего дня)

Однако существующая функция сохраняет только вышеупомянутые данные в таблице с такими столбцами.

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 голосов
/ 19 июня 2019

Вы можете использовать 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
0 голосов
/ 19 июня 2019

Очевидно, что есть некоторые крайние случаи, когда этого недостаточно, но оно должно помочь вам начать.

Это предполагает 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 |
+------------+-------------------+
...