我有table
(id
,employee_id
,device_id
,logged_time
) [简化] < / strong>记录来自生物识别设备的员工的出勤情况。
我生成报告,显示每个员工按日期的第一个进出时间。
目前,我可以按日期获取每个员工的第一个进入和结束时间,但我还需要获取每个员工的第一个进入和结束device_id
。条目不按记录时间的顺序排列。
我不希望(也可能不会)使用连接,因为在其中一个报告中,列是动态生成的,并且可能导致数千个连接。此外,这些是子查询,并与其他查询连接以获取更多详细信息。
表和查询的示例设置位于http://sqlfiddle.com/#!9/3bc755/4
第一个显示的是按每个员工的日期列出进入和退出时间
select
attendance_logs.employee_id,
DATE(attendance_logs.logged_time) as date,
TIME(MIN(attendance_logs.logged_time)) as entry_time,
TIME(MAX(attendance_logs.logged_time)) as exit_time
from attendance_logs
group by date, attendance_logs.employee_id
第二个是根据日期范围建立出勤图
select
`attendance_logs`.`employee_id`,
DATE(MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-18' THEN `attendance_logs`.`logged_time` END)) as date_2017_09_18,
MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-18' THEN `attendance_logs`.`logged_time` END) as entry_2017_09_18,
MAX(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-18' THEN `attendance_logs`.`logged_time` END) as exit_2017_09_18,
DATE(MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-19' THEN `attendance_logs`.`logged_time` END)) as date_2017_09_19,
MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-19' THEN `attendance_logs`.`logged_time` END) as entry_2017_09_19,
MAX(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-19' THEN `attendance_logs`.`logged_time` END) as exit_2017_09_19
/*
* dynamically generated columns for dates in date range
*/
from `attendance_logs`
where `attendance_logs`.`logged_time` >= '2017-09-18 00:00:00' and `attendance_logs`.`logged_time` <= '2017-09-19 23:59:59'
group by `attendance_logs`.`employee_id`;
尝试:
与使用logged_time
的每个日期的最大值和分钟case
类似,尝试选择device_id
logged_time
最大/最小值。
```MIN(case
when
`attendance_logs.logged_time` = MIN(
case when DATE(`attendance_logs`.`logged_time`)
= '2017-09-18' THEN `attendance_logs`.`logged_time` END
)
then `attendance_logs`.`device_id` end) as entry_device_2017_09_18 ```
这导致invalid use of group by
答案 0 :(得分:0)
使用GROUP_CONCAT
SUBSTRING_INDEX
快速查找您的查询以选择进出的设备ID
SUBSTRING_INDEX(GROUP_CONCAT(case when DATE(`l`.`logged_time`) = '2017-09-18' THEN `l`.`device_id` END ORDER BY `l`.`device_id` desc),',',1) exit_device_2017_09_18,
或者,如果每个in和out的设备ID都相同,那么只需用GROUP_CONCAT
编写
GROUP_CONCAT(DISTINCT case when DATE(`l`.`logged_time`) = '2017-09-18' THEN `l`.`device_id` END)
答案 1 :(得分:0)
为避免加入,我建议您尝试相关的子查询&#34;代替:
select
employee_id
, logdate
, TIME(entry_time) entry_time
, (select MIN(l.device_id)
from attendance_logs l
where l.employee_id = d.employee_id
and l.logged_time = d.entry_time) entry_device
, TIME(exit_time) exit_time
, (select MAX(l.device_id)
from attendance_logs l
where l.employee_id = d.employee_id
and l.logged_time = d.exit_time) exit_device
from (
select
attendance_logs.employee_id
, DATE(attendance_logs.logged_time) as logdate
, MIN(attendance_logs.logged_time) as entry_time
, MAX(attendance_logs.logged_time) as exit_time
from attendance_logs
group by
attendance_logs.employee_id
, DATE(attendance_logs.logged_time)
) d
;
请参阅:http://sqlfiddle.com/#!9/06e0e2/3
注意:我在这些子查询上使用了MIN()和MAX(),以避免它们返回多个值的可能性。如果您愿意,可以使用限制1 。
另请注意:我通常不建议使用相关子查询,因为它们可能会导致性能问题,但它们确实提供了您需要的数据。
哦,请尽量避免使用date
作为列名,这不是一个好习惯。