题解与简单优化/浅谈隐式排序

2021年国庆在北京接单3次及以上的司机统计信息

http://www.nowcoder.com/practice/992783fd80f746d49e790d33ee537c19

题意

给你一张用户打车记录表,和一张打车记录表,请你查询出2021年国庆7天期间,在北京接单至少三次的司机平均的接单数和平均兼职收入

思路:

  • 首先,我们需要查询出的是每个司机的平均接单数和平均的兼职收入,但每个司机的接单数和收入不是既存字段,所以我们需要先获取这两个数据才行
  • 获取这两个数据的同时,我们也要限制订单的时间和接单地点,并在分组后筛选出接单数大于3的,SQL如下

SQL1

SELECT
	t1.driver_id,
	COUNT(t1.order_id) AS 'order_num',
	SUM(t1.fare) AS 'income'
FROM
	tb_get_car_order AS t1
	INNER JOIN tb_get_car_record AS t2 ON t1.order_id = t2.order_id
WHERE DATE(finish_time) BETWEEN '2021-10-01' AND '2021-10-07'
AND t2.city = '北京'
GROUP BY driver_id
HAVING COUNT(t1.order_id) >= 3
  • 有了这两个字段后,我们再统计平均接单数和收入即可,SQL如下
SELECT
    '北京' AS 'city',
    ROUND(AVG(t1.order_num), 3) AS 'avg_order_num',
    ROUND(AVG(t1.income), 3) AS 'avg_income'
FROM (
    SQL1
    ) AS t1

优化

  • 查看执行计划的开销: 10.50
  • 由于我们使用了子查询,而子查询的数据量较大,所以这里使用了物化表(将子查询结果放到临时表中,并建立哈希(较少)/B+索引(较多)),因此后面两个表的select_type为DERIVED,且PRIMARY表的表名为derived2
  • 今天借着这单题整点花活: MySQL5.7的隐式排序(implicit sort),即MySQL5.7中会在GROUP BY后面默认为分组字段加上一个排序(2019.4在MySQL8.0中已经移除)
  • 因此,明明没有写ORDER BY,但我们的执行计划Extra中有一个"Using filesort"
  • 其余的"Using where"、"Using temporary"和"Using join buffer"就比较常规了,即临时表分组,回表和存储驱动表记录的join buffer    

alt alt     分析

  • 先从解决隐式排序开始,我们其实并不需要排序,所以这里我们使用ORDER BY NULL来避免排序,相应的再加上对应的索引,不过对应数据量少,开销并未减少 alt    

官方文档

alt alt

MySQL练习 文章被收录于专栏

解析牛客网中的SQL题目

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-03 18:22
投了几百份简历,专业和方向完全对口,都已读不回。尝试改了一下学校,果然有奇效。
steelhead:这不是很正常嘛,BOSS好的是即便是你学院本可能都会和聊几句,牛客上学院本机会很少了
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 14:08
点赞 评论 收藏
分享
炫哥_:哥们项目描述里面vector和mysql之类的都要写吗,直接开头技术栈巴拉巴拉就行了,完全不是技术点啊
点赞 评论 收藏
分享
湫湫湫不会java:先投着吧,大概率找不到实习,没实习的时候再加个项目,然后把个人评价和荣誉奖项删了,赶紧成为八股战神吧,没实习没学历,秋招机会估计不多,把握机会。或者说秋招时间去冲实习,春招冲offer,但是压力会比较大
点赞 评论 收藏
分享
评论
9
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务