I have two tables which are joined - one holds schedules and the other holds actual worked times.
This works fine if a given user only has a single schedule on a day but when they have more than one schedule I cannot get the query to match up the "right" slot to the right time.
I am beginning to think the only way to do this is to allocate the time to the schedule when the clock event happens but that is going to be a big rewrite so I am hoping there is a way in MySQL.
As this is inside a third party application, I am limited in what I can do to the query - I can modify the basics like from, group, joins etc and I can add aggregates to the fields (I have toyed with using min/max on the times). However, if the only way is to write a hugely complex query especially within the field selections then this system simply doesn't give me that option.
Schedule table:
CREATE TABLE `schedule` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` date NOT NULL,
`start_time` time NOT NULL,
`end_time` time NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `schedule`
--
INSERT INTO `schedule` (`id`, `user_id`, `date`, `start_time`, `end_time`) VALUES
(1, 1, '2019-07-07', '08:00:00', '12:00:00'),
(2, 1, '2019-07-07', '16:00:00', '22:00:00'),
(3, 1, '2019-07-06', '10:00:00', '18:00:00');
Time table
CREATE TABLE `time` (
`id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`date` date NOT NULL,
`start_time` time NOT NULL,
`end_time` time NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `time`
--
INSERT INTO `time` (`id`, `user_id`, `date`, `start_time`, `end_time`) VALUES
(1, 1, '2019-07-07', '08:00:00', '12:00:00'),
(2, 1, '2019-07-07', '16:00:00', '22:00:00'),
(3, 1, '2019-07-06', '10:00:00', '18:00:00');
Current query
select
t.date as date, t.user_id,
s.start_time as schedule_start,
s.end_time as schedule_end,
t.start_time as actual_start,
t.end_time as actual_end
from time t
left join schedule s on
t.user_id=s.user_id and t.date=s.date
group by t.date, t.start_time
Current output
== Dumping data for table s
|2019-07-06|1|10:00:00|18:00:00|10:00:00|18:00:00
|2019-07-07|1|08:00:00|12:00:00|08:00:00|12:00:00
|2019-07-07|1|08:00:00|12:00:00|16:00:00|22:00:00
Desired output
== Dumping data for table s
|2019-07-06|1|10:00:00|18:00:00|10:00:00|18:00:00
|2019-07-07|1|08:00:00|12:00:00|08:00:00|12:00:00
|2019-07-07|1|16:00:00|22:00:00|16:00:00|22:00:00
Is this possible to achieve?
I would try something like this. I selected 15 min time limit that a shift should start
select
t.date as date, t.user_id,
s.start_time as schedule_start,
s.end_time as schedule_end,
t.start_time as actual_start,
t.end_time as actual_end
from time t
left join schedule s on
t.user_id=s.user_id and t.date=s.date
and s.start_time BETWEEN t.start_time - INTERVAL 15 MINUTE
AND t.start_time + INTERVAL 15 MINUTE
order by date,schedule_start;
Grouping would you do be add up time for every day and user day
You need a much more complicated query to distinguish the 2 shifts.
So you must execute 2 separate queries each for each shift and combine them with UNION:
select
s.date, s.user_id,
s.schedule_start,
s.schedule_end,
t.actual_start,
t.actual_end
from (
select s.date, s.user_id,
min(s.start_time) as schedule_start,
min(s.end_time) as schedule_end
from schedule s
group by s.date, s.user_id
) s left join (
select t.date, t.user_id,
min(t.start_time) as actual_start,
min(t.end_time) as actual_end
from time t
group by t.date, t.user_id
) t on t.user_id=s.user_id and t.date=s.date
union
select
s.date, s.user_id,
s.schedule_start,
s.schedule_end,
t.actual_start,
t.actual_end
from (
select s.date, s.user_id,
max(s.start_time) as schedule_start,
max(s.end_time) as schedule_end
from schedule s
group by s.date, s.user_id
) s left join (
select t.date, t.user_id,
max(t.start_time) as actual_start,
max(t.end_time) as actual_end
from time t
group by t.date, t.user_id
) t on t.user_id=s.user_id and t.date=s.date
See the demo .
Results:
> date | user_id | schedule_start | schedule_end | actual_start | actual_end
> :--------- | ------: | :------------- | :----------- | :----------- | :---------
> 2019-07-06 | 1 | 10:00:00 | 18:00:00 | 10:00:00 | 18:00:00
> 2019-07-07 | 1 | 08:00:00 | 12:00:00 | 08:00:00 | 12:00:00
> 2019-07-07 | 1 | 16:00:00 | 22:00:00 | 16:00:00 | 22:00:00
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.