在MySQL组内订购

时间:2019-07-07 19:47:21

标签: mysql

我有两个连接在一起的表-一个保存时间表,另一个保存实际工作时间。

如果给定用户一天只有一个时间表,但是当他们有多个时间表时,我无法获得查询以将“正确”时段与正确时间进行匹配。

我开始认为做到这一点的唯一方法是在发生时钟事件时将时间分配到日程表,但这将是一个很大的重写,所以我希望MySQL中有一种方法。

由于这是在第三方应用程序内部,因此我对查询的操作受到限制-我可以修改诸如from,group,joins等的基础知识,并且可以向字段中添加聚合(我喜欢使用最小/最大次数)。但是,如果唯一的方法是编写一个非常复杂的查询(尤其是在字段选择内),则该系统根本不会提供该选项。

时间表表:

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');

时间表

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');

当前查询

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

当前输出

== 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

所需的输出

== 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

这有可能实现吗?

2 个答案:

答案 0 :(得分:1)

我会尝试这样的事情。 我选择了开始换班的15分钟时间限制

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;

分组会为您每天和用户一天的累计时间做一个

答案 1 :(得分:1)

您需要更复杂的查询来区分这两个转变。
因此,您必须为每个班次分别执行2个单独的查询,并将其与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

请参见demo
结果:

> 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