songyichao 2016-10-13 21:55:10 4276次浏览 0条评论 0 0 0

工作的业务逻辑要求取出最近的登录时间,对此有两种解决方法,第一种是针对每个用户执行一次数据库查询,第二种是将一个列表中的用户登录时间一次性全部取出,再遍历数据时,进行数据整合。
第一种方法最简单,但是对数据库的压力比较大,而且很容易造成数据库连接数过大,导致数据库暂时无法连接的问题,所以我采用的是第二种查询方式,第二种查询有效的减少了数据库的操作。登录历史是一直新增的,而且需要查出不重复的最新的记录,就需要先进行数据的排序,再进行分组,但是数据库的执行顺序是先分组,再排序。所以这儿就需要进行子查询,在子查询中进行排序,之后再进行分组,这样可以解决问题代码如下(用的是YII框架就先行贴出yii代码)

$subQuery = (new Query())
    ->select(['service_id', 'ctime'])
    ->from(self::tableName())
    ->where(['service_id' => $service_id])
    ->orderBy(['service_id' => SORT_DESC, 'ctime' => SORT_DESC]);
$res = (new Query())
    ->from(['tmp' => $subQuery])
    ->groupBy(['service_id'])
    ->all(self::getDb());
return $res;
SELECT * FROM (SELECT service_id , ctime  FROM `login_history` WHERE service_id IN ('qweqeq','qweqwe','asdasda', 'asdsasdasd')  ORDER BY `service_id` DESC, `ctime` DESC) `tmp` GROUP BY `service_id`

但是出问题了,在测试环境的mysql 5.7 中group by 的获取数据机制变了,无论怎么排序都是获取插入数据时的第一条记录,所以上面的程序就出现了bug,无法获取到相应的记录。所以在获取时做了改进,代码如下

$subQuery = (new Query())
	->select(['DISTINCT (service_id)', 'ctime'])
	->from(self::tableName())
	->where(['service_id' => $service_id])
	->orderBy(['service_id' => SORT_DESC, 'ctime' => SORT_DESC]);
$res = (new Query())
	->from(['tmp' => $subQuery])
	->groupBy(['service_id'])
	->all(self::getDb());
return $res;
SELECT * FROM (SELECT DISTINCT (service_id) , ctime  FROM `login_history` WHERE service_id IN ('dsfsfs','qweqwe','qweqe', 'wewew')  ORDER BY `service_id` DESC, `ctime` DESC) `tmp` GROUP BY `service_id`

我的理解是在子查询中distinct先获取了数据,然后group by完成了分组。

原文链接

    没有找到数据。
您需要登录后才可以评论。登录 | 立即注册