mysql - 一个sql的问题
问题描述
stat表 字段 uid,act,time我想取出每个uid最近的一个act我现在的sql:
select * from (select * from stat order by uid,time desc) a group by uid
这个表数据量比较大,查起来有点慢,有没有更好的办法
甚至这个:
select act,count(*) num from (select * from (select * from stat order by uid,time desc) a group by uid) b group by act
表:
CREATE TABLE `stat` ( `uid` varchar(40) COLLATE utf8_unicode_ci NOT NULL, `act` bigint(20) NOT NULL, `time` bigint(20) DEFAULT NULL, PRIMARY KEY (`uid`,`act`), KEY `index_time` (`time`) USING BTREE, KEY `index_act` (`act`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
问题解答
回答1:先说一下我的看法吧,如果有错误的地方,欢迎指正。首先,我觉得题主的SQL语句是错的,看起来结果正确只不过是寄希望于数据库在执行group by的实现机制。比如说如果把排序顺序变一下结果就错了。在使用group by之后,题主能够查询的字段要么是在聚集函数里面,要么就是group by的字段,类似于’select * from a group by uid’这样的写法不规范,因为数据库在按照uid分组之后,会随机选取一组act和time的字段值。题主的SQL看起来工作正常应该是在排序之后,数据库默认选取了排序最靠前的。我认为正确的SQL应该是这样的:
select stat.* from stat ,(select uid,max(time) as time from stat group by uid) tmp where stat.uid=tmp.uid and stat.time=tmp.time;
先分组查询出每个人执行时间最晚的时间,然后根据uid和time去获取完整的操作信息。如果题主的数据库对uid加了索引的话,这个 SQL的查询效率应该还在可以接受的程度。一点个人看法。
我在原来的基础之上,做了一丢丢修改,在本地测试性能有微小的提升,我本地是三万组测试数据,题主可以试一下:
select stat.* from stat ,(select uid,max(time) as time from stat group by uid order by null) tmp where stat.time=tmp.time and stat.uid=tmp.uid;回答2:
给查询条件的那几个列建立索引试试,B数索引呀,B+数索引呀等等
具体怎么建立你可以去百度搜一下
回答3:这个语句为什么要嵌套子查询,一条语句不行吗,不是很清楚逻辑,,,不过正常情况下我都是用explain打印一下查询信息
回答4:一条group by就足够了为什么要写两层
相关文章:
1. android - NavigationView 的侧滑菜单中如何保存新增项(通过程序添加)2. 老师 我是一个没有学过php语言的准毕业生 我希望您能帮我一下3. 编程学习心得分享(共80条)4. 关于thinkphp 5.1中,ajax提交数据url的格式写法,加花括号就出错,请老师指点5. php7.3.4中怎么开启pdo驱动6. tp5 不同控制器中的变量调用问题7. 提示语法错误语法错误: unexpected ’abstract’ (T_ABSTRACT)8. 这段代码既不提示错误也看不到结果,请老师明示错在哪里,谢谢!9. ueditor上传服务器提示后端配置项没有正常加载,求助!!!!!10. php - 一个操作请求多个服务如何保证数据的安全?
