背景:由于项目运营需要提供各个球员(playerId)跑动距离(distance)最长的前两场比赛数据记录:
数据存在mongojg表中下面看第一版sql:
1.一开始不知道怎么取跑动最好的前两场数据所以通过取表现最好的比赛然后通过id从结果集排除再对剩下的比赛取最好表现,最后将两次结果合并的到球员表现最好的两场比赛(不多说都是泪)...
SELECT e.ids, e.matchId, e.playerId, e.distance 跑动距离, e.printSpeedDistance, e.highSpeedDistance, ( e.printSpeedDistance + e.highSpeedDistance ) 高强度跑动距离, e.successPass 成功传球次数, e.tackles 阻截 , b.`name` from mongojg e JOIN qiuyaunxinxix b ON e.playerId = b.id JOIN sheet1 c ON b.`name` = c.`球员` WHERE e.distance in (SELECT max(a.distance) 跑动距离 FROM mongojg a JOIN qiuyaunxinxix b ON a.playerId = b.id GROUP BY a.playerId ORDER BY a.playerId);
第二版逻辑:
后来通过子查询的方式实现了取每个球员最好的两场比赛,不多说直接放sql:
SELECT matchId, playerId,b.`name` 球员, distance 跑动距离, ( mj.printSpeedDistanceCounts + mj.highSpeedDistanceCounts ) 高强度跑动距离次数, mj.successPass 成功传球次数, mj.tackles 阻截 from mongojg mj JOIN qiuyaunxinxix b on mj.playerId=b.id WHERE ( SELECT COUNT(1) from mongojg mn WHERE mj.playerId=mn.playerId AND mj.distance<mn.distance )<2 ORDER BY mj.playerId;
可以看到第二版sql比第一版逻辑清晰了很多:加入子查询找出子表中距离比原表大的记录并在这些记录中取前两个记录;
看看执行记录:执行时间1.306s,使用了子查询,下面怎么将子查询改写为left join
优化三:
SELECT mj.matchId, mj.playerId, b.`name` as 球员, mj.distance 跑动距离,mn.distance, ( mj.printSpeedDistanceCounts + mj.highSpeedDistanceCounts ) 高强度跑动距离次数, mj.successPass 成功传球次数, mj.tackles 阻截 FROM mongojg mj JOIN qiuyaunxinxix b ON mj.playerId = b.id LEFT JOIN mongojg mn on mj.playerId=mn.playerId and mn.distance > mj.distance GROUP BY mj.matchId, mj.playerId ,mj.distance HAVING COUNT(mn.matchId)<2 ORDER BY mj.playerId;
执行时间:0.291s,可以看到改为left join连接后效率提升明显;
下一波优化为主表playerId 添加索引:
ALTER TABLE `haha`.`mongojg` ADD INDEX `index`(`playerId`) USING BTREE;
执行时间:时间: 0.017s