MySQL数据去重并只保留每种数据最新一条
项目中用到数据统计,统计当前在线用户(1小时内)最新的定位信息。因为每个用户几分钟内就会产生一条定位信息,且不确定多少用户在线,所以第一想到的笨方法就是直接对一小时内用户去重,得到列表后循环查库找到每个用户的最新一条。太Low,需要优化。
// 表名 track
SELECT t1.*
FROM track AS t1
LEFT JOIN track AS t2
ON t1.user_id = t2.user_id AND t1.created_at < t2.created_at
WHERE t2.id IS NULL;
// 通过改动 t1.login_time < t2.login_time 可自定义筛选符合条件的某条信息
// 在 thinkphp5.0 中实现
$list = Track::alias('t1')
->join('track t2', 't1.imei = t2.imei AND t1.created_at < t2.created_at', 'LEFT')
->whereTime('t1.created_at', '-1 hour')
->where('t2.id IS NULL')
->field('t1.*')
->select();
类似的统计操作还有比较好用的SQL语句:
// 将数据根据天数统计每天的平均值
Model::>where('其他条件')
->fieldRaw("FROM_UNIXTIME(created_at, '%d') AS day,AVG(heart) AS val")
->group('day')
->select();
这里只是统计每天的平均值,在fieldRaw中用好MySQL函数再配合分组就能实现非常复杂的统计情景。