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

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题目

全部评论

相关推荐

11-15 17:19
湖南大学 Java
成果成果成果果:这是哪个公司的hr,这么离谱吗,我没见过用性别卡技术岗的,身边女性同学拿大厂offer的比比皆是
点赞 评论 收藏
分享
ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
9 1 评论
分享
牛客网
牛客企业服务