mysql版本5.6,还用不了ONLY_FULL_GROUP_BY特性。
需求,获取要给学生跟每个老师的最近10条对话
表结构
mysql> desc ts_messages;
+---------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------------+------+-----+---------+----------------+
| message_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| lecturer_id | bigint(20) unsigned | NO | MUL | NULL | |
| student_id | bigint(20) unsigned | NO | | NULL | |
| message_body | varchar(512) | NO | | NULL | |
| created_at | datetime | NO | | NULL | |
| created_by | bigint(20) unsigned | NO | | NULL | |
+---------------------+---------------------+------+-----+---------+----------------+
如果只是获取最新一条数据,做一个desc排序,然后group by lecturer_id,student_id即可
select * from (select lecturer_id,student_id,message_body,created_at from ts_messages order by created_at desc) t group by t.lecturer_id,t.student_id;
只用一条语句获取最近10条对话
set @lec_id=0,@stu_id=0,@num=0;
select * from (select lecturer_id,student_id,message_body,created_at,case when @lec_id=lecturer_id and @stu_id=student_id then @num:=@num+1 else @num:=1 end num,@lec_id:=lecturer_id,@stu_id:=student_id from ts_messages order by student_id,lecturer_id,created_at desc) t where t.num<=10;
原理:
select lecturer_id,student_id,message_body,created_at,case when @lec_id=lecturer_id and @stu_id=student_id then @num:=@num+1 else @num:=1 end num,@lec_id:=lecturer_id,@stu_id:=student_id from ts_messages order by student_id,lecturer_id,created_at desc
获取老师id、学生id成组的所有对话,并计数
case when @lec_id=lecturer_id and @stu_id=student_id then @num:=@num+1
order by student_id,lecturer_id
学生+老师成组,并计数
不成组则是下一组,重置计数
else @num:=1
select * from t where t.num<=10;
获取计数小于等于10的,也就是最近的10条
弊端:
计数时,会计数所有记录,即使使用where lecturer_id=101或者where student_id=102,如果一个人的对话对象太多也是一笔不小的开销。