我有一个GROUP BY
子句的查询。此查询需要员工" checkin" records
表中的时间,如果dn
字段 1 ,则该员工在办公室,但如果 2 ,然后他/她离开了。
所以我想把records.dn
放在GROUP BY
子句中。这导致每个员工的重复条目(我在一个表中一个接一个地得到他们的名字,两次)。
我尝试在选择中使用MIN和MAX,但这根本没有意义。
因此,从数据库中可能多次签入和签出的多行中,如何获取最新行并使用其dn
字段?
这是我正在谈论的问题:
select
MAX(records.dn),
`records`.`din`,
`users`.`username`,
`users`.`id` as `user_id`,
DATE(records.created_at) AS date,
TIME(MIN(records.created_at)) AS first_log,
TIME(MAX(records.created_at)) AS last_log
from `records`
inner join `users` on `records`.`din` = `users`.`din`
where records.created_at BETWEEN '2016-09-05 00:00:00'
AND '2016-09-08 00:00:00'
group by `users`.`username`, DATE(records.created_at)
order by `first_log` asc
(第一个选择列是我尝试做的,使用MAX)
这是包含一些样本数据的记录表:
我如何实现我所寻找的目标?
答案 0 :(得分:1)
substring_index()
/ group_concat()
技巧可能完全符合您的要求:
select substring_index(group_concat(r.dn order by created_at desc), ',', 1) as last_dn,
u.username, u.id as `user_id`,
DATE(r.created_at) AS date,
TIME(MIN(r.created_at)) AS first_log,
TIME(MAX(r.created_at)) AS last_log
from records r inner join
users u
on r.din = u.din
where r.created_at >= '2016-09-05' and
r.created_at < '2016-09-08'
group by u.username, DATE(r.created_at)
order by first_log asc;
如上所述,这有三个局限性:
dn
中没有逗号(可以通过使用不同的分隔符轻松修复)。dn
列表不会超过group_concat()
字符串的最大长度。这也可以使用系统参数进行调整。 last_dn
是一个字符串,即使它不是原始类型。但这种技巧在大多数情况下效果很好。参数group_concat_max_len
是中间字符串的大小。它的默认值(此处为described)为1,024。对于多达一百个或更多整数,这应该没问题。这是一个会话参数,很容易更改。
另请注意以下更改:
between
,因为它具有包容性。我猜你要在8日之前严格要求日期/时间值。