Подсчитать количество отработанных дней в месяце, исключая отпуска и больничные - PullRequest
1 голос
/ 06 июня 2019

Мне нужно получить для каждого пользователя, сколько дней недели они проработали (в месяце), у меня есть таблица, в которой хранится диапазон дат, в котором они не работали (отпуск по болезни), и таблица учета, в которой хранятся рабочие дни.

ausentismoT хранит нерабочие дни как диапазоны дат, таблица выглядит следующим образом

user ini        fin        --ini = start date | fin = end date
---------------------------
john 06/05/2019 06/05/2019
john 13/05/2019 13/05/2019
john 20/05/2019 24/05/2019

Таблица подсчета, хранящая каждый день месяца и помечающая их статус как праздник:

IDCal   fechaValor  numDiaSemana    nomDia  nomMes  semanaAno   diaJuliano  feriadoBancario feriadoNombre
---------------------------------------------------------------------------------------------
20190502    2019-05-02 00:00:00.000 4   Jueves  Mayo    18  122 0   NULL
20190503    2019-05-03 00:00:00.000 5   Viernes Mayo    18  123 0   NULL
20190504    2019-05-04 00:00:00.000 6   Sábado  Mayo    18  124 1   Weekend

Мой код, который я знаю, что логика неверна, я "пытаюсь" исключить как праздничные, так и нерабочие дни, но результаты равны 0 во всех столбцах:

SELECT T.RUT_DV,
T.USER,
DIAS_HAB_MES = (SELECT COUNT(CONVERT(INT,feriadoBancario,112)) AS D FROM CALENDAR C WHERE feriadoBancario=0 AND CONVERT(NVARCHAR(6),C.fechaValor,112) = CONVERT(NVARCHAR(6),GETDATE(),112)),

LUNES = (SELECT COUNT(CONVERT(INT,feriadoBancario,112)) AS D FROM CALENDAR C 
    WHERE numDiaSemana=1 AND feriadoBancario = 0 AND (FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0) AND T2.INI) AND FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, getdate()), 0)-1 AND T2.FIN),

MARTES = (SELECT COUNT(CONVERT(INT,feriadoBancario,112)) AS D FROM CALENDAR C 
    WHERE numDiaSemana=2 AND feriadoBancario = 0 AND (FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0) AND T2.INI) AND FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, getdate()), 0)-1 AND T2.FIN),

MIERCOLES = (SELECT COUNT(CONVERT(INT,feriadoBancario,112)) AS D FROM CALENDAR C 
    WHERE numDiaSemana=3 AND feriadoBancario = 0 AND (FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0) AND T2.INI) AND FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, getdate()), 0)-1 AND T2.FIN),

JUEVES = (SELECT COUNT(CONVERT(INT,feriadoBancario,112)) AS D FROM CALENDAR C 
    WHERE numDiaSemana=4 AND feriadoBancario = 0 AND (FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0) AND T2.INI) AND FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, getdate()), 0)-1 AND T2.FIN),

VIERNES = (SELECT COUNT(CONVERT(INT,feriadoBancario,112)) AS D FROM CALENDAR C 
    WHERE numDiaSemana=5 AND feriadoBancario = 0 AND (FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0) AND T2.INI) AND FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, getdate()), 0)-1 AND T2.FIN)

FROM dotacionAD T -- BASE TABLE
LEFT JOIN ausentismoT T2 ON T.RUT_DV = REPLACE(T2.RUT_DV,'.','')

Результаты таковы:

NOM_COL DIAS_HAB_MES    LUNES   MARTES  MIERCOLES   JUEVES  VIERNES
-------------------------------------------------------------------
JOHN    20  0   0   0   0   0

Для того же случая должно отображаться это:

NOM_COL DIAS_HAB_MES    LUNES   MARTES  MIERCOLES   JUEVES  VIERNES
-------------------------------------------------------------------
JOHN    20  1   3   3   4   4

Ответы [ 2 ]

0 голосов
/ 06 июня 2019

Это должно помочь вам начать. Хотя не совсем ясно, предоставили ли вы всю информацию.

select
    t.user, count(*) as dia_hab_mes,
    count(case when numDiaSemana = 1 then 1 end) as lunes,
    ...
from
    users as u cross join calendar as c
    left outer join ausentismoT as a
        on c.<date> between a.ini and a.fin and a.user = t.user
where c.<date> ... /* filter dates for desired month */
    and feriadoBancario = 0
group by u.user;
0 голосов
/ 06 июня 2019

Я полагаю, что вы допустили ошибку при повторном вставке dateadd / datediff во второй раз.

Когда я пишу этот ответ, мой локальный getdate () вернется 6 июня 2019 года.

Ваше первое условие:

FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0) AND T2.INI

Эта формула усекает текущую дату до уровня месяца, а также вычитает один месяц.Таким образом, если я запусту его сейчас, я получу 1 мая 2019 года. Все ваши ini после этого, так что ОК.

Ваше второе условие:

FECHAVALOR BETWEEN DATEADD(MM, DATEDIFF(MM, 0, getdate()), 0)-1 AND T2.FIN

Эта формула усекает текущийУровень даты к месяцу не вычитает месяц, но в конце вычитает день.Таким образом, если я запусту его сейчас, я получу 2 июня 2019 года. Ни один из твоих плавников не позже этого, и поэтому ты везде получаешь ноль.

Теперь я не уверен, что ты намереваешься увидеть,но два BETWEEN кажутся странными.Если вы хотите, чтобы последние 2 месяца были в ausentismoT, я бы написал так:

FECHAVALOR >= DATEADD(MM, DATEDIFF(MM, 0, GETDATE())-1, 0)
AND
FECHAVALOR BETWEEN T2.INI and T2.FIN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...