mysql - 考虑到某些数据可以重叠,计算受限于某些数据的范围内的天数

标签 mysql

假设我有一个名为“contracts”的表,其中包含以下列:iddate_fromdate_toid_user .

我想在给定日期范围的情况下计算用户在该范围内有多少天签订了契约(Contract),而不管她有多少份契约(Contract)(也就是说,即使有重叠契约(Contract),也只计算一次天数) .

例如,给定此数据:

id      date_from     date_to        id_user
1       2016-10-26    2018-12-13     5
2       2017-11-10    2018-12-13     5
3       2018-06-01    2019-12-13     5
4       2018-10-01    2018-11-13     6
5       2017-01-01    2018-03-13     10
6       2019-03-12    2020-01-01     10

给定范围

SET @from = '2018-03-12';
SET @to = '2019-03-12';

我想要一个输出的查询:

id_user    days_in_range
5          365
6          43
10         2

最佳答案

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,date_from DATE NOT NULL
,date_to DATE NULL
,id_user INT NOT NULL
);

INSERT INTO my_table VALUES
(1,'2016-10-26','2018-12-13',5),
(2,'2017-11-10','2018-12-13',5),
(3,'2018-06-01','2019-12-13',5),
(4,'2018-10-01','2018-11-13',6),
(5,'2017-01-01','2018-03-13',10),
(6,'2019-03-12','2020-01-01',10);

SELECT id_user 
     , MIN(date_from) date_from
     , date_to 
  FROM 
     ( SELECT x.id_user
            , LEAST(x.date_from,COALESCE(y.date_from,x.date_from)) date_from
            , MAX(GREATEST(x.date_to,COALESCE(y.date_to,x.date_to))) date_to 
         FROM my_table x 
         LEFT 
         JOIN my_table y 
           ON y.id_user = x.id_user 
          AND y.date_from <= x.date_to 
          AND y.date_to >= x.date_from 
          AND y.id > x.id 
        GROUP 
           BY id_user,date_from
     ) a 
 GROUP 
    BY id_user,date_to;
+---------+------------+------------+
| id_user | date_from  | date_to    |
+---------+------------+------------+
|       5 | 2016-10-26 | 2019-12-13 |
|       6 | 2018-10-01 | 2018-11-13 |
|      10 | 2017-01-01 | 2018-03-13 |
|      10 | 2019-03-12 | 2020-01-01 |
+---------+------------+------------+

SELECT id_user
     , SUM(DATEDIFF(LEAST('2019-03-12',date_to),GREATEST('2018-03-12',date_from))) delta 
  FROM
     ( SELECT id_user 
            , MIN(date_from) date_from
            , date_to 
         FROM 
            ( SELECT x.id_user
                   , LEAST(x.date_from,COALESCE(y.date_from,x.date_from)) date_from
                   , MAX(GREATEST(x.date_to,COALESCE(y.date_to,x.date_to))) date_to 
                FROM my_table x 
                LEFT 
                JOIN my_table y 
                  ON y.id_user = x.id_user 
                 AND y.date_from <= x.date_to 
                 AND y.date_to >= x.date_from 
                 AND y.id > x.id 
               GROUP 
                  BY id_user,date_from
            ) a 
        GROUP 
           BY id_user
            , date_to
     ) m
 WHERE '2018-03-12' <= date_to
   AND '2019-03-12' >= date_from
 GROUP
    BY id_user;

+---------+-------+
| id_user | delta |
+---------+-------+
|       5 |   365 |
|       6 |    43 |
|      10 |     1 |
+---------+-------+

(我认为我没有正确解释事件 A 与事件 B 与事件 C 重叠的位置,但是嘿,这是给我的数据集)

关于mysql - 考虑到某些数据可以重叠,计算受限于某些数据的范围内的天数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55124597/

相关文章:

php - mysqli 动态生成的表,带有打开包含行中所有值的表单的链接

mysql - 多个查询上的节点Mysql未定义字段

php - 我可以单独从服务器端 PHP 填充 "Google Charts"吗?

python - 迁移: Creating UserProfile in Django/MySQL

java - Android 应用程序建立与服务器的连接?

PHP - 实现主键 SQL

php - 将 PHP fetch 变量传递到另一个页面

javascript - jQuery 和 mysql 在点击时更新数据

php - 如何在 anchor 标记中调用php变量

mysql - 将数据行选择为月份