select每个用户最近date的行
我有一个表(“lms_attendance”)的用户入住和出院时间如下所示:
id user time io (enum) 1 9 1370931202 out 2 9 1370931664 out 3 6 1370932128 out 4 12 1370932128 out 5 12 1370933037 in
我试图创build一个这个表的视图,只输出每个用户ID最近的logging,同时给我的“in”或“out”值,所以如下所示:
id user time io 2 9 1370931664 out 3 6 1370932128 out 5 12 1370933037 in
我目前非常接近,但是我意识到,意见不会接受subquerys,这使得它更难。 我得到的最接近的查询是:
select `lms_attendance`.`id` AS `id`, `lms_attendance`.`user` AS `user`, max(`lms_attendance`.`time`) AS `time`, `lms_attendance`.`io` AS `io` from `lms_attendance` group by `lms_attendance`.`user`, `lms_attendance`.`io`
但是我得到的是:
id user time io 3 6 1370932128 out 1 9 1370931664 out 5 12 1370933037 in 4 12 1370932128 out
哪个接近,但不完美。 我知道最后一组不应该在那里,但没有它,它会返回最近的时间,但不会与它的相对IO值。
有任何想法吗? 谢谢!
查询:
SQLFIDDLEExample
SELECT t1.* FROM lms_attendance t1 WHERE t1.time = (SELECT MAX(t2.time) FROM lms_attendance t2 WHERE t2.user = t1.user)
结果:
| ID | USER | TIME | IO | -------------------------------- | 2 | 9 | 1370931664 | out | | 3 | 6 | 1370932128 | out | | 5 | 12 | 1370933037 | in |
每次工作的解决scheme:
SQLFIDDLEExample
SELECT t1.* FROM lms_attendance t1 WHERE t1.id = (SELECT t2.id FROM lms_attendance t2 WHERE t2.user = t1.user ORDER BY t2.id DESC LIMIT 1)
没有必要尝试重新发明轮子,因为这是最常见的每组问题 。 介绍了非常好的解决scheme 。
我更喜欢最简单的解决scheme( 请参阅SQLFiddle,更新Justin的 )没有子查询(因此易于在视图中使用):
SELECT t1.* FROM lms_attendance AS t1 LEFT OUTER JOIN lms_attendance AS t2 ON t1.user = t2.user AND (t1.time < t2.time OR (t1.time = t2.time AND t1.Id < t2.Id)) WHERE t2.user IS NULL
这也适用于在同一组中有两个不同logging具有相同最大值的情况 – 感谢(t1.time = t2.time AND t1.Id < t2.Id)
的技巧。 我在这里所做的只是确保在同一用户的两个logging具有相同时间的情况下,只有一个被select。 实际上,如果标准是Id
还是别的什么都不重要 – 基本上任何保证是独一无二的标准都可以在这里find工作。
基于@TMS的答案,我喜欢它,因为不需要子查询,但我认为省略'OR'
部分将是足够的,更容易理解和阅读。
SELECT t1.* FROM lms_attendance AS t1 LEFT JOIN lms_attendance AS t2 ON t1.user = t2.user AND t1.time < t2.time WHERE t2.user IS NULL
如果您对空行的行不感兴趣,则可以在WHERE
子句中对它们进行过滤:
SELECT t1.* FROM lms_attendance AS t1 LEFT JOIN lms_attendance AS t2 ON t1.user = t2.user AND t1.time < t2.time WHERE t2.user IS NULL and t1.time IS NOT NULL
已经解决了,但只是为了logging,另一种方法是创build两个视图…
CREATE TABLE lms_attendance (id int, user int, time int, io varchar(3)); CREATE VIEW latest_all AS SELECT la.user, max(la.time) time FROM lms_attendance la GROUP BY la.user; CREATE VIEW latest_io AS SELECT la.* FROM lms_attendance la JOIN latest_all lall ON lall.user = la.user AND lall.time = la.time; INSERT INTO lms_attendance VALUES (1, 9, 1370931202, 'out'), (2, 9, 1370931664, 'out'), (3, 6, 1370932128, 'out'), (4, 12, 1370932128, 'out'), (5, 12, 1370933037, 'in'); SELECT * FROM latest_io;
点击这里查看它在SQL小提琴的行动
试试这个查询:
select id,user, max(time), io FROM lms_attendance group by user;
select b.* from (select `lms_attendance`.`user` AS `user`, max(`lms_attendance`.`time`) AS `time` from `lms_attendance` group by `lms_attendance`.`user`) a join (select * from `lms_attendance` ) b on a.user = b.user and a.time = b.time
可能你可以按用户分组,然后按时间顺序sorting。 像下面这样
SELECT * FROM lms_attendance group by user order by time desc;