MySQL查询时间表信息

时间:2015-06-24 03:03:38

标签: mysql sql sql-tuning

我在MySQL中有一个表如下:

+----+--------+------------------+------+  
| id | userid | fecha_ingreso    | tipo |  
+----+--------+------------------+------+  
|  1 | 1      | 2015-06-08 20:00 | 1    |  
|  3 | 1      | 2015-06-09 05:00 | 2    |  
| 18 | 2      | 2015-06-09 23:30 | 1    |  
| 19 | 2      | 2015-06-10 05:00 | 2    |  
| 20 | 2      | 2015-06-10 06:00 | 1    |  
| 21 | 2      | 2015-06-10 09:00 | 2    |  
| 22 | 1      | 2015-06-09 23:30 | 1    |  
| 23 | 1      | 2015-06-10 05:00 | 2    |  
| 24 | 1      | 2015-06-10 06:00 | 1    |  
| 25 | 1      | 2015-06-10 09:00 | 2    |  
+----+--------+------------------+------+  
10 rows in set  

此表包含进入工作和离开工作的每个用户(userid)的信息(fecha_ingreso)。例如,userid=1已在tipo=1输入('2015-06-08 20:00'),而他将工作留在'2015-06-09 05:00'

然后我输入了userid=2 tipo=1'2015-06-09 23:30'(夜间)工作,他离开(tipo=2)工作,在{{1}吃早餐他再次进入'2015-06-10 05:00'并最终离开'2015-06-10 06:00'工作。

我无法进行只向我显示此类内容的查询:

'2015-06-10 09:00'

这是我需要的输出。即使用户可以有多个细节,我也需要显示他的第一个入口日期时间和最后一个日期时间,并附上一个专栏,说明他在工作时间为22:00和次日凌晨6点的工作时数和分钟数

蒂姆,你的查询很完美,但它几近接近。但是,当用户在22点之后(我的样本显示)时,我不知道如何获得小时:分钟:秒。

1 个答案:

答案 0 :(得分:0)

计算总工作时间应该更容易,假设工人可以在晚上8点之后上班,最多工作10个小时(你可以调整):

select userid, time_ins, cnt_start, time_outs, cnt_end, seconds,     TIME_FORMAT(SEC_TO_TIME(seconds),'%H:%i:%s') as night_shift
from (
select userid, time_ins, cnt_start, time_outs, cnt_end, 
(select sum(timestampdiff(second, cnt_start,
                case when fecha_ingreso < a.cnt_start then a.cnt_start  
                    when fecha_ingreso > a.cnt_end then a.cnt_end
                    else fecha_ingreso end )  * case when tipo =1 then -1 else 1 end ) seconds 
    from test_t n
    where n.userid = a.userid and n.fecha_ingreso >= a.time_ins and n.fecha_ingreso <=a.time_outs) seconds
from (
 select userid, time_ins, cnt_start, time_outs , 
 case when cast(time_outs as date) = cast(time_ins as date) then time_outs 
    when cast(time_outs as time)>'06:00:00' then       date_add(date(time_outs), interval 6 hour) end cnt_end
 from (
 select userid, time_enter as time_ins , case when cast(time_enter as time) < '20:00:00' then 
    date_add(date(time_enter), interval 22 hour)
     else time_enter end as cnt_start,
     (select max(fecha_ingreso) from test_t l where l.userid=e.userid and l.tipo=2 and l.fecha_ingreso > e.time_enter 
     and l.fecha_ingreso < date_add(e.time_enter, interval 22 hour) )
    as time_outs
  from (
    select userid, min(fecha_ingreso) as time_enter 
      from test_t 
      where cast(fecha_ingreso as time)>='06:00:00'
      and tipo=1
      group by userid ,cast(fecha_ingreso as date)
    ) e
   ) t
  ) a
) ff;

我没有对其进行优化,因此您可以看到这些步骤。

您可以尝试:

select l1.* from l1 
left join (
select l.id, m.id  mid from l1 l 
join l1 m
on l.userid=m.userid and l.tipo=2 and m.tipo=1 and l.fecha_ingreso >=date_add(m.fecha_ingreso, interval -1 hour)
and l.id < m.id) x
on l1.id=x.id or l1.id =x.mid
where mid is null;

它返回

# id, userid, fecha_ingreso, tipo
'1', '1', '2015-06-08 20:00:00', '1'
'3', '1', '2015-06-09 05:00:00', '2'
'18', '2', '2015-06-09 23:30:00', '1'
'21', '2', '2015-06-10 09:00:00', '2'
'22', '1', '2015-06-09 23:30:00', '1'
'25', '1', '2015-06-10 09:00:00', '2'

在1小时内过滤掉同一用户的1-2个条目。