关于mysql5.5和5.7group的区别

工作的业务逻辑要求取出最近的登录时间,对此有两种解决方法,第一种是针对每个用户执行一次数据库查询,第二种是将一个列表中的用户登录时间一次性全部取出,再遍历数据时,进行数据整合。

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

// PHP CODE

$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;

// MYSQL CODE

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,无法获取到相应的记录。所以在获取时做了改进,代码如下

// PHP CODE

$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;

// MYSQL CODE

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完成了分组。