一、题目相关内容
1)相关的表和题目
2)帮助理解题目的示例,提供返回结果的格式
二、自己初步的理解
一群人要上巴士但是巴士有体重限制,那只能有限个人才能上去
最后输出这个最后一个上去还不超重的人的名字
我认为首先要缩小记录数,只有能上车的人先出现,但是我想不到怎么才能做到。于是还是老老实实看题解吧。
三、题解展示和分析
1.官方题解
SELECT a.person_name
FROM Queue a, Queue b
WHERE a.turn >= b.turn
GROUP BY a.person_id HAVING SUM(b.weight) <= 1000
ORDER BY a.turn DESC
LIMIT 1
分析题解过程如下:
1)又是自连接也是交叉连接,通过每个人和其他所有人连接,找到自己在里面的位置,留下之前人和自己即可。
2)将每个人进行分组。
3)现在利用每个分组里自己和之前人的体重之和看看是否大于1000。
真的太巧妙了,这样就筛选出来了
自己回忆和思考的这个题解如下,
select a.person_name from queue a,queue b where a.turn>=b.turn group by a.person_id having sum(b.weight)<=1000 order by b.turn desc limit 1;
并提交上去的时候显示解答错误,如下图,但是由于这个测试用例比较长不方便看,我就如下图添加了下测试用例就在右下角全部显示出来了,然后发现自己的答案和正确答案有区别,order by的字段是不一样的,发现我的是b.turn,正确答案是a.turn。
我筛选出的结果是第16个名字teach前面一个名字,正确答案是后面的名字dragon。
评论区有人问了为什么排序的字段是a.turn,有一个解答但是我还是不理解,怎么想都想不出来,有大佬知道为什么吗?
2.不用自连接的方式,用窗口函数,如下
select person_name
from(select turn,person_name,sum(weight) over(order by turn) as cumu_weight from Queue) t
where cumu_weight <= 1000
order by turn desc
limit 1
sum()over()这个函数如果我之前知道的话,也是倾向于这一种方法的,因为一直猜测有没有函数能做这样的操作。
这个题解的核心就是子查询,利用这个窗口函数把turn排序后的累积相加的体重作为一个字段即可
3.加几个题解里有的不同于上面两个的,等着以后思考
select person_name from Queue q1 where (select sum(weight) from Queue where turn <= q1.turn) <= 1000 order by turn desc limit 1;
select person_name from(select turn, person_name, sum(weight) over(order by turn) as cumu_weight from Queue) t where cumu_weight <= 1000 order by turn desc limit 1;
四、总结
官方题解有一个不理解的地方,要等着以后思考了,会了sum()overover()窗口函数,多多思考!!