Как подвести итоги отпуска без выходных? - PullRequest
0 голосов
/ 19 апреля 2019

Привет всем (до праздников).

В этом случае я добавил новый отпуск в эту таблицу:

+--------+---------+---------+-------------+----------+--------------------------
|ID_LEAVE|ID_WORKER| FNAME   | LNAME | BEGIN_DATE         | END_DATE            | 
+--------+---------+---------+---------+-------------+--------------------+------
| 8      |   10    | MARIO   | NEED  |2019-04-22 07:00:00 |2019-04-23 15:00:00  | 
+--------+---------+---------+-------------+----------+-------------------------- 

Но я знаю, что праздники представляют так:

enter image description here

Что я уже сделал?

Я выполнил этот запрос, который суммирует время отпуска всех сотрудников, сгруппированных по ID_LEAVE

SELECT leave.ID_LEAVE, leave.ID_WORKER, workers.FNAME, workers.LNAME, leave.BEGIN_DATE, leave.END_DATE,  
FROM 
(SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value 
 FROM 
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0, 
 (SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1, 
 (SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2, 
 (SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3, 
 (SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) calendar 
INNER JOIN leave ON calendar.date_value BETWEEN DATE(leave.BEGIN_DATE) AND DATE(leave.END_DATE) 
INNER JOIN workers ON leave.ID_WORKER = workers.ID_WORKER 
WHERE NOT WEEKDAY(date_value) IN (5, 6)
GROUP BY ID_LEAVE;

Теперь я бы хотел запрос, в котором суммируется время увольнения всех сотрудников, но без выходных, который я представил на картинке выше. Что мне делать?Должен ли я создать новую таблицу "праздничные дни" и затем загрузить эту дату из этой таблицы или добавить даты в запросе выше?

Ответы [ 3 ]

0 голосов
/ 19 апреля 2019

Вариант без полной таблицы календаря, но с праздничной таблицей, как в вопросе (хотя с полными датами - вам придется заполнять его для каждого года):

SELECT L.id_leave, COUNT(*)
FROM (
    SELECT '1970-01-01' + INTERVAL (seq) DAY AS date
    FROM seq_0_to_24836
) C
INNER JOIN leaves L
    ON C.date BETWEEN L.begin_date AND L.end_date
    AND NOT WEEKDAY(date_value) IN (5, 6)
    AND NOT EXISTS (
        SELECT * FROM holidays H WHERE H.date = C.date
    )
GROUP BY L.id_leave

Примечание: seq_0_to_24836 - расширение только для MariaDB, и здесь будут сгенерированы все даты с эпохи до конца 2037 года.

0 голосов
/ 19 апреля 2019

Хорошо, проанализировав все комментарии и ответ, я нашел это решение:

1) Я создал праздничный стол.

2) Я создал этот запрос, который выбирает все и подводит итоги увольнения без выходных и праздничных дней:

SELECT *, 
TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(TIME(leave.END_DATE), TIME(leave.BEGIN_DATE))))), '%H:%i:%s') AS 'LEAVE TIME' 
FROM 
(SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value FROM 
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0, 
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1, 
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2, 
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3, 
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4) calendar 
INNER JOIN `leave` ON calendar.date_value BETWEEN DATE(leave.BEGIN_DATE) AND DATE(leave.END_DATE) 
WHERE NOT WEEKDAY(date_value) IN (5, 6) AND NOT DATE(date_value) IN (SELECT DATE_HOLIDAY FROM holidays) GROUP BY ID_LEAVE;

Я только что проверил по ссылкам ниже:

https://dbfiddle.uk/?rdbms=mariadb_10.3&fiddle=a25a3dc5762dba08541c002f12efc024

Кто-нибудь предупреждает об этом? Большое спасибо и хорошей Пасхи;)

0 голосов
/ 19 апреля 2019

Если у вас есть таблица календаря, в которой перечислены все дни (не только праздничные дни, но каждый день года в течение следующих X лет, а также столбец, указывающий, является ли этот день государственным праздником и т. Д.), Тогда ваш запрос выглядит следующим образом

SELECT l.id_leave, count(*)
FROM calendar c INNER JOIN leave l ON c.calendar_date BETWEEN l.start_date AND l.end_date
WHERE c.day_type NOT IN ('publicholiday', 'weekend')
GROUP BY l.id_leave

Вы можете добавить намного больше сложности, но это ядро. Не уверен, почему ваши листья начинаются в 7 утра и заканчиваются в 10 вечера, но вы можете добавить некоторую логику, если вы допускаете дробные выходные дни - продлите дату начала обратно до полуночи (так, чтобы промежутки работали правильно), а затем используйте случай, когда построить дробь в зависимости от того, является ли рассматриваемая дата начальной или конечной датой или промежуточной датой

...