Welcome to Subscribe On Youtube
3262. Find Overlapping Shifts 🔒
Description
Table: EmployeeShifts
+++ \| employee_id \| int \| \| start_time \| time \| \| end_time \| time \| ++-+ \| employee_id \| start_time \| end_time \| +-++-+
Output:
+-+--+ \| employee_id \| overlapping_shifts \| +-+--+ \| 1 \| 2 \| \| 2 \| 1 \| \| 4 \| 1 \| +-+--+
Explanation:
- Employee 1 has 3 shifts:
- 08:00:00 to 12:00:00
- 11:00:00 to 15:00:00
- 14:00:00 to 18:00:00
- Employee 2 has 2 shifts:
- 09:00:00 to 17:00:00
- 16:00:00 to 20:00:00
- Employee 3 has 3 shifts:
- 10:00:00 to 12:00:00
- 13:00:00 to 15:00:00
- 16:00:00 to 18:00:00
- Employee 4 has 2 shifts:
- 08:00:00 to 10:00:00
- 09:00:00 to 11:00:00
The output shows the employee_id and the count of overlapping shifts for each employee who has at least one overlapping shift, ordered by employee_id in ascending order.
</div>
Solutions
Solution 1: Self-Join + Group Counting
We first use a self-join to connect the EmployeeShifts
table to itself. The join condition ensures that we only compare shifts belonging to the same employee and check if there is any overlap between shifts.
t1.start_time < t2.start_time
: Ensures that the start time of the first shift is earlier than the start time of the second shift.t1.end_time > t2.start_time
: Ensures that the end time of the first shift is later than the start time of the second shift.
Next, we group the data by employee_id
and count the number of overlapping shifts for each employee.
Finally, we filter out employees with overlapping shift counts greater than $0$ and sort the results in ascending order by employee_id
.
-
import pandas as pd def find_overlapping_shifts(employee_shifts: pd.DataFrame) -> pd.DataFrame: merged_shifts = employee_shifts.merge( employee_shifts, on="employee_id", suffixes=("_t1", "_t2") ) overlapping_shifts = merged_shifts[ (merged_shifts["start_time_t1"] < merged_shifts["start_time_t2"]) & (merged_shifts["end_time_t1"] > merged_shifts["start_time_t2"]) ] result = ( overlapping_shifts.groupby("employee_id") .size() .reset_index(name="overlapping_shifts") ) result = result[result["overlapping_shifts"] > 0] result = result.sort_values("employee_id").reset_index(drop=True) return result
-
SELECT t1.employee_id, COUNT(*) AS overlapping_shifts FROM EmployeeShifts t1 JOIN EmployeeShifts t2 ON t1.employee_id = t2.employee_id AND t1.start_time < t2.start_time AND t1.end_time > t2.start_time GROUP BY 1 HAVING overlapping_shifts > 0 ORDER BY 1;