积累一些常见的写SQL的题

引言


前几天面了美团的一面,在数据库方面本来以为会像阿里一样只问一些基础知识,没想到面试官居然让我写SQL,而且写的都是一些比较复杂的SQL,我都好长时间没写过复杂的SQL了,所以写得相当糟糕,所以在这篇博客中积累几题经典的题。

考察NOT IN子句


例题

有如下的student表,里面记录学生不同科目的成绩:

namesubjectscore
Bob数学90
Bob语文79
Lucy数学81
Lucy语文80

现在要查询出所有成绩都大于80分的所有学生的姓名。

解答

使用NOT IN子句将存在小于80分成绩的学生筛选掉就可以了

SELECT DISTINCT name FROM student 
  WHERE name NOT IN (
    SELECT name FROM student WHERE score < 80
  );

考察LIMIT子句


LIMIT子句的格式

LIMIT [offsets,]rows

offsets表示偏移量是多少(偏移量从0开始),rows表示要查询多少条记录。其中offsets如果不写的话默认就是从0开始。

例题

有如下的student表,里面记录了学生的成绩:

namescore
Bob90
Tom90
Lucy86
Work86
Abel77

现在要查询出所有并列排名第二的学生姓名。

解答

题目中要求考虑并列排名,所以我们先用LIMIT子句把排名第二的分数查出来,如下:

SELECT DISTINCT score FROM student 
  order by score desc LIMIT 1,1;

然后再从student表中查出分数等于这个排名第二的分数的学生,将答案写成一条完整的SQL语句如下:

SELECT * FROM student 
  WHERE score=
    (SELECT DISTINCT score FROM student 
      order by score desc LIMIT 1,1);

考察聚集函数


例题

假设有如下的student表:

nameclassage
Bob120
Tom121
Lucy222
Work123
Abel325

查询出人数在60以上的各个班级的平均年龄

解答

通过HAVING子句筛选出人数在60以上的班级,然后使用AVG聚集函数求出平均年龄。

SELECT class, AVG(age) FROM student 
  GROUP BY class HAVING COUNT(*)>60;

考察ANY与ALL谓词


ANY与ALL谓词

谓词含义
>ANY大于子查询结果中的某个值
>ALL大于子查询结果中的所有值
<ANY小于子查询中的某个值
<ALL小于子查询结果中的所有值

例题

假设有如下的student表:

nameclassage
Bob120
Tom121
Lucy222
Work123
Abel325

查询1班以外比一班年龄最小的学生还要小的学生

解答

使用ALL子句可以很容易的解决

SELECT * FROM student WHERE class<>1 AND 
  age<ALL(
    SELECT age from student WHERE class=1
  );

考察NOT EXISTS子句


NOT EXISTS子句常用于带有”至少”语义的查询问题,在SQL中难度是比较大的

例题1

假设有三张表,分别是student(学生),course(课程),sc(学生选课),表格如下:

  • student表:
idname
0Bob
2Tom
3Lucy
4Work
5Abel
  • course表:
idcourse
0数据库
2计算机网络
3数据结构
4计算机组成原理
5离散数学
  • sc表(是一个连接表,代表学生选课,s_id是学生id,c_id是课程id):
s_idc_id
03
00
14
25
32

问题1:查询选修了全部课程的学生姓名
问题2:查询至少选修了id为1的学生选修的全部课程的学生id

问题1解答

将问题的语义转化为“查询这样的学生,不存在任意一门他没选的课”:

SELECT name FROM student WHERE NOT EXISTS
  (SELECT * FROM course WHERE NOT EXISTS
    (SELECT * FROM sc WHERE sc.s_id=student.id 
      AND sc.c_id=course.id)
  );

问题2解答

将语义转化为“查询这样的学生,不存在任意一门课程,id为1的学生选的但是他没选”:

SELECT s_id FROM sc scx WHERE NOT EXISTS
  (SELECT sc FROM sc scy WHERE scy.id=1 AND
    NOT EXISTS
    (SELECT * FROM sc scz WHERE 
      scx.s_id=scz.s_id AND scy.c_id=scz.c_id) 
  );
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值