在MYSQL中每天获取每位员工的后进先出时间

时间:2019-08-23 03:22:46

标签: mysql sql

很抱歉再次提出基于出勤的问题,但是这里的其他解决方案似乎都不适合我。

我需要每天获取每位员工的“先进先出”列表。表格看起来像这样:

$result =  Master::where(function ($query) use ($request) {
    if ($request->filter == true) {
        $query->where('user_id', Auth::user()->id);
    }
    // other conditions here
    if (!empty($request->area_from) && !empty($request->area_to)) {
        $query->whereHas('one', function ($query) use ($request) {
            $query->whereBetween('area', [$request->area_from, $request->area_to]);
        });
        $query->orWhereHas('two', function ($query) use ($request) {
            $query->whereBetween('area', [$request->area_from, $request->area_to]);
        });
    }
    // other conditions here

})->with(['one', 'two'])->paginate($request->item);

我需要这样的结果:

id  date_time               access  emp_id
1   2016-01-01T09:00:00Z    In      00101
2   2016-01-01T09:10:00Z    In      00302
3   2016-01-01T13:10:00Z    Out     00101
4   2016-01-01T13:05:00Z    Out     00302
5   2016-01-01T14:00:00Z    In      00302
6   2016-01-01T14:10:00Z    In      00101
7   2016-01-01T17:00:00Z    Out     00101
8   2016-01-01T17:10:00Z    Out     00302
9   2016-01-02T09:05:00Z    In      00101
10  2016-01-02T09:10:00Z    In      00302
11  2016-01-02T12:05:00Z    Out     00101
12  2016-01-02T12:35:00Z    Out     00302
13  2016-01-02T13:40:00Z    In      00302
14  2016-01-02T17:15:00Z    Out     00302
15  2016-01-03T08:50:00Z    In      00302
16  2016-01-03T17:10:00Z    Out     00101

因此,在第二天,我知道有1名员工离开去吃午餐,并且没有回来。在第3天的时候,一些员工一直在忙活,需要对通行证使用情况进行授课。

我的问题是,要获得最小/最大时间不是那么简单,因为它们基于访问类型。分别获取进入或退出时间并不困难,但是由于MYSQL中缺少完整的外部联接,因此将它们组合到1个结果表中是很棘手的。

workday     emp_id  entry_time              entry_time
2016-01-01  00101   2016-01-01T09:00:00Z    2016-01-01T17:00:00Z
2016-01-01  00302   2016-01-01T09:10:00Z    2016-01-01T17:10:00Z
2016-01-02  00101   2016-01-02T09:05:00Z    2016-01-02T12:05:00Z
2016-01-02  00302   2016-01-02T09:10:00Z    2016-01-02T17:15:00Z
2016-01-03  00302   2016-01-03T08:50:00Z    0
2016-01-03  00101   0                       2016-01-03T17:10:00Z

请原谅,如果我也没有尝试在这些陈述中尝试左右联接的尝试。

我所能管理的最好是将进入和退出时间放在单独的行上,这并不理想。

select cast(date_time as date) as workday, emp_id, min(date_time) as entry_time from attendance where access = 'In' group by date(date_time), emp_id order by workday;
select cast(date_time as date) as workday, emp_id, max(date_time) as exit_time from attendance where access = 'Out' group by date(date_time), emp_id order by workday;

产生:

select cast(date_time as date) as workday, emp_id, IF (access = 'In', MIN(date_time), 0) as entry_time, IF (access = 'Out', MAX(date_time), 0) as exit_time from attendance group by date(date_time), emp_id, access order by workday;

What I have tried on SQL Fiddle

有什么我想念的吗?有没有更好的做事方法?

感谢您的协助,在此先感谢您。

1 个答案:

答案 0 :(得分:0)

我认为您需要再做一个group by。见下文:

select p.workday, p.emp_id, max(p.time_in), max(p.time_out)
from (
      select cast(date_time as date) as workday, emp_id, 
            min(case when (access='In') then date_time else 0 end) as time_in, 
            max(case when (access='Out') then date_time else 0 end) as time_out
      from attendance
      group by cast(date_time as date), emp_id, access
  ) as p
  group by p.workday, p.emp_id

这将产生预期的结果。这是demo