我有一个包含 GROUP BY
子句的查询。此查询从 records
表中获取员工“签到”时间,如果 dn
字段为 1,则员工在办公室,但是如果是2,那么他/她就离开了。
假设我将 records.dn
放在 GROUP BY
子句中。这导致每个员工都有重复的条目(我在表格中一个接一个地得到他们的名字,两次)。
我尝试在选择中使用 MIN 和 MAX,但这根本没有意义。
因此,从数据库中员工可能多次 checkin 和 checkout 的多行中,我如何获取最新行并使用其 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)
这是带有一些示例数据的记录表:
我如何实现我正在寻找的东西?
最佳答案
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。对于多达一百个或更多的整数,这应该没问题。它是一个 session 参数,很容易更改。
另请注意以下更改:
- 我认为查询中不必要的反引号只会让它更难阅读。
- 使用表别名使查询更易于编写和阅读。
- 我不认为你的意思是
between
,因为它是包容性的。我猜您希望日期/时间值严格在 8 号之前。
关于mysql - 如何让我的 GROUP BY 获取特定列的最后一行(按日期)的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39427044/