Получить количество непрерывных дат в MySQL - PullRequest
1 голос
/ 11 октября 2019

У меня есть требование, чтобы получить количество непрерывных дат в таблице листьев.

CREATE TABLE leaves(
id INT AUTO_INCREMENT PRIMARY KEY ,
employee_id INT NOT NULL,
leave_request_id INT NOT NULL,
leave_date DATE NOT NULL,
start_time time NOT NULL DEFAULT '00:00:00',
end_time time NOT NULL DEFAULT '00:00:00'
);


INSERT INTO `leaves` (`id`, `leave_request_id`, `leave_date`, `employee_id`, `start_time`, `end_time`) VALUES (NULL, '1', '2019-10-01', '2', '09:00:00.000000', '18:00:00.000000'), (NULL, '1', '2019-10-02', '2', '09:00:00.000000', '18:00:00.000000'), (NULL, '1', '2019-10-03', '2', '09:00:00.000000', '18:00:00.000000'), (NULL, '2', '2019-10-08', '2', '09:00:00.000000', '18:00:00.000000'), (NULL, '3', '2019-10-14', '3', '09:00:00.000000', '18:00:00.000000'), (NULL, '4', '2019-10-15', '3', '09:00:00.000000', '18:00:00.000000'), (NULL, '5', '2019-10-16', '3', '09:00:00.000000', '18:00:00.000000'), (NULL, '6', '2019-09-30', '5', '09:00:00.000000', '18:00:00.000000'), (NULL, '6', '2019-10-01', '5', '09:00:00.000000', '18:00:00.000000'), (NULL, '7', '2019-10-01', '8', '09:00:00.000000', '18:00:00.000000');

SqlFiddle Link is: sqlfiddle

У меня есть следующие записи таблицы:

id  employee_id     leave_request_id    leave_date  start_time  end_time
1   2               1                   2019-10-01  09:00:00    18:00:00
2   2               1                   2019-10-02  09:00:00    18:00:00
3   2               1                   2019-10-03  09:00:00    18:00:00
4   2               2                   2019-10-08  09:00:00    18:00:00
5   3               3                   2019-10-14  09:00:00    18:00:00
6   3               4                   2019-10-15  09:00:00    18:00:00
7   3               5                   2019-10-16  09:00:00    18:00:00
8   5               6                   2019-09-30  09:00:00    18:00:00
9   5               6                   2019-10-01  09:00:00    18:00:00
10  8               7                   2019-10-01  09:00:00    18:00:00

Я пробовал следующий запрос, который * GROUP BY листья_секун_длины - это количество последовательных дней в одном идентификаторе_перехода_доставки. Но иногда сотрудник получает последовательные отпуска в одном запросе на отпуск, как в записях с идентификатором 5,6,7. Сотрудник 3 брал последовательные отпуска с 2019-10-14 по 2019-10-16, но с другим запросом на отпуск. Итак, мне нужен дополнительный столбец actual_consect_length , в котором подсчитываются даты последовательных отпусков в каждом листьях по запросу.

Мне нужен вывод, как показано ниже, показывающий столбец actual_consect_length (фактическая длина подряд) со следующимиданные.

employee_id  min_applied_date  max_applied_date  leave_consec_length  actual_consect_length
2            2019-10-01        2019-10-03        3                    3
2            2019-10-08        2019-10-08        1                    1
3            2019-10-14        2019-10-14        1                    3
3            2019-10-15        2019-10-15        1                    3
3            2019-10-16        2019-10-16        1                    3
5            2019-09-30        2019-10-01        2                    2
8            2019-10-01        2019-10-01        1                    1

Любая помощь будет оценена.

1 Ответ

1 голос
/ 15 октября 2019

Sql на самом деле не предназначен для этого, и в 8.0x будет несколько проще с его оконными функциями.

Этот оператор SQL

Select 
  MIN(employee_id) employee_id
  ,min(`leave_date`) min_applied_date  
  ,max(`leave_date`) max_applied_date  
  ,SUM(leavecount) +1 leave_consec_length
  ,Max(t4.activecount) actual_consect_length

FROM
(SELECT 
  employee_id
    ,`leave_date`
    , leave_request_id
  ,if(@leavereq = leave_request_id,IF(employee_id = @employee
          ,1
          ,0),0) leavecount
 ,if(@employee = employee_id,IF(@date = DATE_SUB(leave_date, INTERVAL 1 DAY)
          ,@active := @active +1
          ,@active :=1),@active := 1) activecount
  ,if(@employee = employee_id,IF(@date = DATE_SUB(leave_date, INTERVAL 1 DAY)
          ,@group1 := @group1 
          ,@group1 := @group1 +1),@group1 := @group1 + 1) group1
  ,@employee := employee_id
  ,@leavereq := leave_request_id  
  ,@date := leave_date
  FROM 
    leaves
    , (Select @employee :=0) r
    , (Select @leavereq :=0) s
   , (Select @group1 :=0) u
    , (Select @date := "1970-1-2") t
 ORDER BY employee_id,leave_date) t2 inner join
 ( SELECT
     GROUP_CONCAT(DISTINCT leave_request_id) leave_request_id
   ,group1
   ,max(activecount) activecount
   FROM (
    SELECT
    leave_request_id
    ,if(@employee = employee_id,IF(@date = DATE_SUB(leave_date, INTERVAL 1 DAY)
          ,@active := @active +1
          ,@active :=1),@active := 1) activecount
  ,if(@employee = employee_id,IF(@date = DATE_SUB(leave_date, INTERVAL 1 DAY)
          ,@group := @group 
          ,@group := @group+1),@group := @group+ 1) group1
      ,@employee := employee_id
  ,@date := leave_date
  FROM 
    leaves
    , (Select @employee :=0) r
   , (Select @group :=0) u
    , (Select @date := "1970-1-2") t
     ORDER by employee_id,leave_date) t3
 GROUP BY group1) t4 on FIND_IN_SET (t2.leave_request_id ,t4.leave_request_id)
 GROUP BY t2.Group1,t2.leave_request_id
 ORDER BY employee_id,min_applied_date;

Предоставляет вам этот результат

employee_id     min_applied_date    max_applied_date leave_consec_length  ctual_consect_length
2               2019-10-01          2019-10-03        3                   3
2               2019-10-08          2019-10-08        1                   1
3               2019-10-14          2019-10-14        1                   4
3               2019-10-15          2019-10-15        1                   4
3               2019-10-16          2019-10-16        1                   4
3               2019-10-17          2019-10-17        1                   4
5               2019-09-30          2019-10-01        2                   2
8               2019-10-01          2019-10-01        1                   1

new Пример dbfiddle https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=4a3f5c1f8070631771a52a195d9f4f55

t2 получает все данные, которые вы хотите + оставьтеconsec_length.

t4 получает действительную длину последовательных дней

Редактировать: Для работы таких алгоритмов их необходимо правильно отсортировать

...