获取 mysql 中连续日期的计数

Get count of continuous dates in mysql

我需要计算树叶中连续日期的数量 table。

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 是:sqlfiddle

我有以下 table 条记录:

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 leave_request_id.

SELECT employee_id,
       min(leave_date) AS min_applied_date, 
       max(leave_date) AS max_applied_date, 
       SUM(1) AS consec_length_days 
FROM leaves 
GROUP By leave_request_id;

在上面的查询中,min_applied_date 是单个 leave_request_id 中的最小日期,max_applied_date 是单个 leave_request_id 中的最大日期。 leave_consec_length 是单个 leave_request_id 中的连续天数。但是,有时,员工会在单个请假请求中连续请假,例如在 ID 为 5、6、7 的记录中。员工 3 从 2019-10-14 到 2019-10-16 连续请假,但请假请求不同。所以,我想要额外的列 actual_consect_length 来计算每个 leave_request.

中的连续休假日期

我想要如下所示的输出意味着显示列 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

如有任何帮助,我们将不胜感激。

Sql 并不是真正为此而设计的,在 8.0x 中它的 window 功能会更容易一些。

这个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 为您提供所需的所有数据 + leaveconsec_length。

t4 获取实际连续长度天数

编辑:要使此类算法正常工作,必须对其进行正确排序