Consider the following schema;
CREATE TABLE `Project Assignment`
(`Employee` varchar(1), `Project Id` int, `Project Assignment Date` date, `Project Relieving Date` date)
;
INSERT INTO `Project Assignment`
(`Employee`, `Project Id`, `Project Assignment Date`, `Project Relieving Date`)
VALUES
('A', 1, '2018-04-01', '2019-12-25'),
('A', 2, '2019-06-15', '2020-03-31'),
('A', 3, '2019-09-07', '2020-05-20'),
('A', 4, '2020-07-14', '2020-12-15')
;
CREATE TABLE `Break`
(`Break Id` int, `Employee` varchar(1), `Project Id` int, `Break Start Date` date, `Break End Date` date)
;
INSERT INTO `Break`
(`Break Id`, `Employee`, `Project Id`, `Break Start Date`, `Break End Date`)
VALUES
(1, 'A', 1, '2018-09-01', '2018-09-30'),
(2, 'A', 1, '2019-10-05', '2019-11-30'),
(3, 'A', 2, '2019-10-15', '2019-11-15'),
(4, 'A', 3, '2019-11-01', '2019-11-10'),
(5, 'A', 2, '2020-01-01', '2020-01-10'),
(6, 'A', 3, '2020-01-01', '2020-01-10')
;
During a project, an employee can take one or more breaks in each Project. The breaks don't overlap within Project but can overlap across projects.
We want Count of Days on which an Employee had at least one project assigned (minus) the days on which the employee was on break on all assigned projects.
I was able to derive Distinct Days the Employee was assigned to Projects by using below query:
SELECT merged.employee,
SUM(DATEDIFF(merged.EndDate,merged.`Project Assignment Date`)+1) assigned_days
FROM (SELECT
s1.employee, s1.`Project Assignment Date`,
MIN(IFNULL(t1.`Project Relieving Date`,CURDATE())) AS EndDate
FROM `Project Assignment` s1
INNER JOIN `Project Assignment` t1
ON t1.employee = s1.employee
AND s1.`Project Assignment Date` <= IFNULL(t1.`Project Relieving Date`,CURDATE())
AND NOT EXISTS( SELECT * FROM `Project Assignment` t2
WHERE t2.employee = s1.employee
AND IFNULL(t1.`Project Relieving Date`,CURDATE()) >= t2.`Project Assignment Date`
AND IFNULL(t1.`Project Relieving Date`,CURDATE()) < IFNULL(t2.`Project Relieving Date`,CURDATE()))
WHERE NOT EXISTS( SELECT * FROM `Project Assignment` s2
WHERE s2.employee = s1.employee
AND s1.`Project Assignment Date` > s2.`Project Assignment Date`
AND s1.`Project Assignment Date` <= IFNULL(s2.`Project Relieving Date`,CURDATE()))
GROUP BY s1.employee, s1.`Project Assignment Date`
ORDER BY s1.`Project Assignment Date`) merged
GROUP BY merged.employee
Result:
| employee | assigned_days |
| -------- | ------------- |
| A | 936 |
But couldn't think of a way to derive days on which the person was on break on all assigned projects.
Expected Result:
+----------+---------------+------------+-------------+
| employee | assigned_days | break_days | worked_days |
+==========+===============+============+=============+
| A | 936 | 50 | 886 |
+----------+---------------+------------+-------------+
Mariadb 10.3.29
Explanation of working out break_days
+----------+---------+-------------+------------------+-----------------+-------------------------------------------------------------------------------------------------------------------+
| Employee | Project | Break Start | Break End | Days Considered | Remarks |
+==========+=========+=============+==================+=================+===================================================================================================================+
| A | 1 | 2018-09-01 | 2018-09-30 | 30 | Only one project assigned so consider whole break |
+----------+---------+-------------+------------------+-----------------+-------------------------------------------------------------------------------------------------------------------+
| A | 1 | 2019-10-05 | 2019-11-30 | 10 | 3 Projects were assigned during these breaks. The common days of break fall between 2019-11-01 and 2019-11-10 |
+----------+---------+-------------+------------------+ | |
| A | 2 | 2019-10-15 | 2019-11-15 | | |
+----------+---------+-------------+------------------+ | |
| A | 3 | 2019-11-01 | 2019-11-10 | | |
+----------+---------+-------------+------------------+-----------------+-------------------------------------------------------------------------------------------------------------------+
| A | 2 | 2020-01-01 | 2020-01-10 | 10 | 2 Projects were assigned during this time and break in both projects |
+----------+---------+-------------+------------------+ | |
| A | 3 | 2020-01-01 | 2020-01-10 | | |
+----------+---------+-------------+------------------+-----------------+-------------------------------------------------------------------------------------------------------------------+
| | | | Total Break Days | 50 | |
+----------+---------+-------------+------------------+-----------------+-------------------------------------------------------------------------------------------------------------------+
Link for DB-Fiddle: https://www.db-fiddle.com/f/c8fMneAUkhb2P3rzjMtVZm/0