假设我有一个名为“contracts”的表,其中包含以下列:id
、date_from
、date_to
、id_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/