SQL分组取前三(包含并列)问题

撸SQL的人经常会碰到这种问题,分组取前几。这个问题也常常作为大厂的面试题之一。

最常见的解决方法是使用x>(count(*))这种,也是大厂面试的标准答案之一。我们来推演一下:

先看下表结构,我们来取每班前3名、前2名和第1名:

标准解答是这样的:

select * from ADU_TEST T
where 3>(select count(*) from ADU_TEST where CLASS=T.CLASS and SCORE>T.SCORE)

结果的确是我们想要的。

我们拆分来理解一下这条SQL。查询ADU_TEST表中的数据,条件是每个班的前三名。也就是同一个班中(CLASS=T.CLASS),比其分数高的(SCORE>T.SCORE),且小于3人的。括号中是一条自连接查询

运行原理:首先匹配一班,从1表中SCORE=10,依次跟2表中SCORE=10,20,30,40,50,60,70,80比较,结果=7不<3,舍;

                                        再到1表中SCORE=20,依次跟2表中SCORE=10,20,30,40,50,60,70,80比较,结果=6不<3,舍;                                            。

                                           。

                                           。

                                        再到1表中SCORE=60,依次跟2表中SCORE=10,20,30,40,50,60,70,80比较,结果=2<3,留;

                                        再到1表中SCORE=70,依次跟2表中SCORE=10,20,30,40,50,60,70,80比较,结果=1<3,留;

                                        再到1表中SCORE=80,依次跟2表中SCORE=10,20,30,40,50,60,70,80比较,结果=0<3,留;

 

                 依次匹配二班、三班。

OK,语句也理解了,也背过了,大功告成。

实际并没什么luan用。

我写SQL的这些年,还从未在生产环境下用过这条语句。原因很简单,他的原理就是IF...FOR...IF...FOR。实际工作中几乎不存在这么一张表,直接存储我们想要的这种数据结构。而是在一个复杂的子查询中再进行分组排列取前几。而基于这条语句的运行原理我们可以看出,他的效率是极其低下的。

以下为真实案例:

真实的需求是在这条子查询基础上,根据C_VIP_ID分组,找出前三,我们用刚才的方法试一下:

很明显,这个很多大厂作为标准答案的方法,在实际业务上并不是很实用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值