6. SQL题目练习
为什么你必须写好SQL?¶
在我们工作中,无论是业务人员,还是开发人员,或是管理者,如今,几乎每个人都必须使用某种形式的数据,因为数据毕竟是信息的呈现,要获取信息必须得依赖数据,而这些数据通常是以电子表格或是数据库的形式存放。
现状1:从业务人员视角来看,在企业里面,我们当前的现状就是,业务人员想要看哪些数据得依赖开发人员从数据库中提取数据,而这一过程需要漫长的等待,影响工作效率,如果我们懂简单的SQL,自己能从数据库提取数据,那么工作效率就会有大的提升,在同样的岗位中能够脱颖而出
现状2:从数据分析师视角来看,习SQL几乎成为数分必备的技能,如果这个技能不达标,基本上很难通过面试,而且近几年SQL面试的题目也越来越难,要想通过面试几乎成为数据分析师必须且深度掌握的技能。
现状3:从数据开发者角度来看,对于数据开发者来讲,典型的像数仓同学,基本天天与SQL打交道,这里其实与数据分析岗位有交叉的部分,对于SQL的掌握不言而喻。
SQL语法很简单,但几乎没几个人写的很好
这里不得不提国内语言的鄙视链,在大多数程序员眼里,他们认为SQL称不上一门语言,因为门槛太低,语法很简单就几个命令就能搞定,不需要专门学,或是成为一种岗位。有这种认识的往往都不是从事数据相关的人员,他们实际工作中使用SQL语言也很简单,就是简单的增删改查,甚至有时候面试问他们分组TOPN的问题都会难倒一大片,而对从事数据开发或数据分析师来讲,分组TOPN问题却很简单,这就是平时工作方向的不同带来的误区。不同的岗位有不同的工作方向和重点,我们不能以语言简单程度来区分岗位的优劣,或有鄙视心里,因为毕竟语言只是一种工具,而程序员最重要的还是逻辑思维能力,如果我拿语法比较简单的语言比如SQL去处理复杂的业务逻辑,其实未必就是一件简单的事情,他背后需要的是数据处理的逻辑思维及业务知识,其实此时SQL仅仅只是个工具。
在国外Data Science面试中,对SQL的考察,其实要求很高,很多公司要求必须熟练掌握SQL相关基础语法,并具备极强的数据处理思维逻辑,很多面试者也在SQL考察环节栽了跟头。在众多求职者中,我们分析其原因,这些求职者并不是不懂SQL语法,而是缺乏数据分析的思维能力,缺乏必要的实战技巧。甚至我们经常跟很多经验丰富数仓开发同学去聊,他们在用SQL解决实际业务问题时,都是这样的处理逻辑,遇到要分析的指标,先分析指标的含义,搞清楚逻辑及需要取数的源表后,就开始像套公式般找各种内置的函数去套,看看哪种函数能帮我解决业务问题,像极了某些语言开发者去寻找API的过程。但作为成熟的开发者来说,我们在处理数据问题或写代码时是这样吗?这里我们先打个问号,留给读者自己体会。倘若我们的业务逻辑稍微复杂些,套用函数或API套不动了怎么办?业务不做了吗?去跟业务撕逼吗?哈哈,我想办法总比困难多。这也就是我们所说的工作了好多年,你发现没几个人会把SQL写的很好,实际上呢?遇到复杂的业务逻辑或面试题也会凉凉。。。。。。当然实在不行了,我们也可以换语言实现嘛,总之办法总比困难多。最后,对于一个成熟的SQLer,不仅仅只是停留在实现业务逻辑的角度,更重要的一点还要从底层执行引擎的角度去理解SQL执行过程,看懂执行计划,并能写出性能较高的SQL。
SQL题目练习¶
--创建表student
create table student(
name varchar(10),
kecheng varchar(10),
fengshu int
)
--插入数据到表student中
insert into student values('张三','语文',81);
insert into student values('张三','数学',75);
insert into student values('李四','语文',76);
insert into student values('李四','数学',90);
insert into student values('王五','语文',81);
insert into student values('王五','数学',100);
insert into student values('王五','英语',90);
-- 查询出每门课都大于80分的学生姓名
-- 因为一个学生有多门课程,可能所有课程都大于80分,可能有些课程大于80分,另外一些课程少于80分,也可能所有课程都小于80分。
-- 那么我们要查找出所有大于80分的课程的学生姓名,我们可以反向思考,找出课程小于80分(可以找出有一些课程小于80分,所有课程小于80分的学生)的学生姓名再排除这些学生剩余的就是所有课程都大于80分的学生姓名了。
select distinct name from student where name not in (select distinct name from student where fengshu<=80);
/* not in */
SELECT DISTINCT A.name FROM student A WHERE A.name not in(SELECT Distinct S.name FROM student S WHERE S.score <80);
/* not exists */
SELECT DISTINCT A.name From student A where not exists (SELECT 1 From student S Where S.score <80 AND S.name =A.name);
SQL案例题¶
-- 建库
CREATE DATABASE `emp`;
-- 打开库
USE emp;
-- 部门信息表(部门编号,部门名称,位置)
CREATE TABLE `dept`(
`deptno` INT(2) NOT NULL,
`dname` VARCHAR(14),
`loc` VARCHAR(13),
CONSTRAINT pk_dept PRIMARY KEY(deptno)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 员工信息表(员工编号,员工姓名,工作职位,上级领导,入职日期,月薪,津贴,部门编号)
CREATE TABLE `emp` (
`empno` int(4) NOT NULL PRIMARY KEY,
`ename` VARCHAR(10),
`job` VARCHAR(9),
`mgr` int(4),
`hiredate` DATE,
`sal` float(7,2),
`comm` float(7,2),
`deptno` int(2),
CONSTRAINT fk_deptno FOREIGN KEY(deptno) REFERENCES dept(deptno)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 薪水等级信息表(等级,最低薪水,最高薪水)
CREATE TABLE `salgrade` (
`grade` int,
`losal` int,
`hisal` int
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 数据
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');
INSERT INTO dept VALUES (30,'SALES','CHICAGO');
INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,'1987-07-13',3000,NULL,20);
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,'1981-11-07',5000,NULL,10);
INSERT INTO emp VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,'1987-07-13',1100,NULL,20);
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);
-- 1. 列出与"SCOTT"从事相同工作的所有员工及部门名称。
-- 获取SCOTT的工作
SELECT job FROM emp WHERE ename='SCOTT'
-- 关联部门表,获取部门名称,查出(员工,部门)
SELECT e.ename, d.dname FROM emp e, dept d WHERE e.job =( SELECT job FROM emp WHERE ename = 'SCOTT' ) AND e.ename<>'SCOTT' AND e.deptno=d.deptno
-- 2. 列出公司各个工资等级雇员的数量、平均工资。
SELECT s.grade,count(*),avg(e.sal) FROM emp e LEFT JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal GROUP BY s.grade ;
-- 3. 列出薪金高于在部门30工作的所有员工的薪金的员工姓名和薪金、部门名称。
select ename,sal,d.dname,d.deptno from emp e left join dept d on e.deptno = d.deptno where e.sal > (select max(sal) from emp where deptno = 30);
-- 4. 列出在每个部门工作的员工数量、平均工资和平均服务期限。
select count(*),avg(sal),avg(year(now())-year(hiredate)) from emp group by deptno;
-- 5. 列出所有员工的姓名、部门名称和工资。
select e.ename,d.dname,e.sal from emp e left join dept d on d.deptno = e.deptno;
-- 6. 列出所有部门的详细信息和部门人数
select d.*,count(e.ename) from dept d left join emp e on e.deptno = d.deptno group by d.deptno;
-- 7. 列出各种工作的最低工资及从事此工作的雇员姓名。
select t.job ,a.ename , t.minsal from emp a left join (select e.job as job , min(e.sal) as minsal from emp e group by e.job) t on a.job = t.job;
-- 8. 列出各个部门的MANAGER(经理)的最低薪金、姓名、部门名称、部门人数。
select a.mm,c.ename,c.job,b.dname,b.cc from (select d.deptno,min(sal) mm from emp e left join dept d on e.deptno = d.deptno where job = 'MANAGER' group by deptno) a left join (select d.deptno,d.dname,count(*) cc from emp e left join dept d on e.deptno = d.deptno group by d.deptno) b on a.deptno = b.deptno left join emp c on c.sal = a.mm and b.deptno = c.deptno ;
-- 9. 列出所有员工的年工资,所在部门名称,按年薪从低到高排序。
select empno,ename,sal * 12 ,d.dname from emp left join dept d on d.deptno = emp.deptno order by sal * 12 asc;
-- 10. 查出某个员工的上级主管及所在部门名称,并要求出这些主管中的月薪超过3000
-- 11. 求出部门名称中,带"S"字符的部门员工的、工资合计、部门人数。
-- 12. 给任职日期超过30年或者在87年雇佣的雇员加薪,加薪原则:10部门增长10%,20部门增长20%, 30部门增长30%,依次类推。
-- 13. 列出至少有一个员工的所有部门的信息。
select DISTINCT d.* from dept d join emp e on d.deptno = e.deptno;
-- 14. 列出月薪比JAMES低的所有员工。
select * from emp where sal < (select sal from emp where ename = 'JAMES')
-- 15. 列出所有员工的姓名以及其直接上级的姓名。
select a.empno,a.ename as 'e_name',b.ename as 'm_name' from emp a left join emp b on a.mgr = b.empno;
-- 16. 列出受雇日期早于其直接上级的所有员工的编号、姓名,部门名称。
-- 17. 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。
-- 18. 列出所有"CLERK(职员)"的姓名以及部门名称,部门的人数。
-- 19. 列出最低薪金大于1500的各种工作以及从事此工作的全部雇员人数。
-- 20. 列出在部门"SALES"工作的员工的姓名,假定不知道销售部的部门编号。
-- 21. 列出薪金高于公司平均薪金的所有员工,所在部门,上级领导,公司的工资等级。
-- 22. 列出至少有一个员工的所有部门编号、名称,并统计出这些部门的平均工资、最低工资、最高工 资。
-- 23. 列出薪金比“SMITH”或“ALLEN”多的所有员工的编号、姓名、部门名称、其领导姓名。
-- 24. 列出所有员工的编号、姓名及其直接上级的编号、姓名,显示的结果按领导年工资的降序排列。
-- 25. 列出受雇日期早于其直接上级的所有员工的编号、姓名、部门名称、部门位置、部门人数。
-- 26. 列出部门名称和这些部门的员工信息(数量、平均工资),同时列出那些没有员工的部门。
-- 27. 列出所有“CLERK”(办事员)的姓名及其部门名称,部门的人数,工资等级。
-- 28. 列出最低薪金大于1500的各种工作及此从事此工作的全部雇员人数及所在部门名称、位置、平均工 资。
-- 29. 列出在部门“SALES”(销售部)工作的员工的姓名、基本工资、雇佣日期、部门名称,假定不知道 销售部的部门编号。
-- 30. 列出薪金高于公司平均薪金的所有员工,所在部门,上级领导,公司的工资等级。
-- 31. 列出与“SCOTT”从事相同工作的所有员工及部门名称,部门人数。
-- 32. 查询dept表的结构
-- 33. 检索emp表,用is a 这个字符串来连接员工姓名和工种两个字段
-- 34. 检索emp表中有提成的员工姓名、月收入及提成。
-- DDL
-- 学生表
-- Student(SId,Sname,Sage,Ssex)
-- SId 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别
-- 课程表
-- Course(CId,Cname,TId)
-- CId 课程编号,Cname 课程名称,TId 教师编号
-- 教师表
-- Teacher(TId,Tname)
-- TId 教师编号,Tname 教师姓名
-- 成绩表
-- SC(SId,CId,score)
-- SId 学生编号,CId 课程编号,score 分数
create table Student(sid varchar(10),sname varchar(10),sage datetime,ssex nvarchar(10));
insert into Student values('01' , '赵雷' , '1990-01-01' , '男');
insert into Student values('02' , '钱电' , '1990-12-21' , '男');
insert into Student values('03' , '孙风' , '1990-05-20' , '男');
insert into Student values('04' , '李云' , '1990-08-06' , '男');
insert into Student values('05' , '周梅' , '1991-12-01' , '女');
insert into Student values('06' , '吴兰' , '1992-03-01' , '女');
insert into Student values('07' , '郑竹' , '1989-07-01' , '女');
insert into Student values('08' , '王菊' , '1990-01-20' , '女');
create table Course(cid varchar(10),cname varchar(10),tid varchar(10));
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');
create table Teacher(tid varchar(10),tname varchar(10));
insert into Teacher values('01' , '张三');
insert into Teacher values('02' , '李四');
insert into Teacher values('03' , '王五');
create table SC(sid varchar(10),cid varchar(10),score decimal(18,1));
insert into SC values('01' , '01' , 80);
insert into SC values('01' , '02' , 90);
insert into SC values('01' , '03' , 99);
insert into SC values('02' , '01' , 70);
insert into SC values('02' , '02' , 60);
insert into SC values('02' , '03' , 80);
insert into SC values('03' , '01' , 80);
insert into SC values('03' , '02' , 80);
insert into SC values('03' , '03' , 80);
insert into SC values('04' , '01' , 50);
insert into SC values('04' , '02' , 30);
insert into SC values('04' , '03' , 20);
insert into SC values('05' , '01' , 76);
insert into SC values('05' , '02' , 87);
insert into SC values('06' , '01' , 31);
insert into SC values('06' , '03' , 34);
insert into SC values('07' , '02' , 89);
insert into SC values('07' , '03' , 98);
-- 1. 查询“01”课程比“02”课程成绩高的所有学生的学号;
select distinct t1.sid as sidfrom
(select * from sc where cid='01')t1
left join
(select * from sc where cid='02')t2
on t1.sid=t2.sid
where t1.score>t2.score
-- 2. 查询平均成绩大于60分的同学的学号和平均成绩;
select
sid
,avg(score)
from sc
group by sid
having avg(score)>60
-- 3. 查询所有同学的学号、姓名、选课数、总成绩
select
student.sid as sid
,sname
,count(distinct cid) course_cnt
,sum(score) as total_score
from student
left join sc
on student.sid=sc.sid
group by sid,sname
-- 4. 查询姓“李”的老师的个数;
select
count(distinct tid) as teacher_cnt
from teacher
where tname like '李%'
-- 5. 查询没学过“张三”老师课的同学的学号、姓名;
select
sid,sname
from student
where sid not in
(
select
sc.sid
from teacher
left join course
on teacher.tid=course.tid
left join sc
on course.cid=sc.cid
where teacher.tname='张三'
)
-- 6. 查询学过“01”并且也学过编号“02”课程的同学的学号、姓名;
select
t.sid as sid
,sname
from
(
select
sid
,count(if(cid='01',score,null)) as count1
,count(if(cid='02',score,null)) as count2
from sc
group by sid
having count(if(cid='01',score,null))>0 and count(if(cid='02',score,null))>0
)t
left join student
on t.sid=student.sid
-- 7. 查询学过“张三”老师所教的课的同学的学号、姓名;
select
student.sid
,sname
from
(
select
distinct cid
from course
left join teacher
on course.tid=teacher.tid
where teacher.tname='张三'
)course
left join sc
on course.cid=sc.cid
left join student
on sc.sid=student.sid
group by student.sid,sname
-- 8. 查询课程编号“01”的成绩比课程编号“02”课程低的所有同学的学号、姓名;
select
t1.sid,sname
from
(
select distinct t1.sid as sid
from
(select * from sc where cid='01')t1
left join
(select * from sc where cid='02')t2
on t1.sid=t2.sid
where t1.score>t2.score
)t1
left join student
on t1.sid=student.sid
-- 9. 查询所有课程成绩小于60分的同学的学号、姓名;
select
t1.sid,sname
from
(
select
sid,max(score)
from sc
group by sid
having max(score<60)
)t1
left join student
on t1.sid=student.sid
-- 10. 查询没有学全所有课的同学的学号、姓名;
select
t1.sid,sname
from
(
select
count(cid),sid
from sc
group by sid
having count(cid) < (select count(distinct cid) from course)
)t1
left join student
on t1.sid=student.sid
-- 11. 查询至少有一门课与学号为“01”的同学所学相同的同学的学号和姓名;
select
distinct sc.sid
from
(
select
cid
from sc
where sid='01'
)t1
left join sc
on t1.cid=sc.cid
-- 12. 查询和"01"号的同学学习的课程完全相同的其他同学的学号和姓名
#注意是和'01'号同学课程完全相同但非学习课程数相同的,这里我用左连接解决这个问题select
t1.sid,sname
from
(
select
sc.sid
,count(distinct sc.cid)
from
(
select
cid
from sc
where sid='01'
)t1 #选出01的同学所学的课程
left join sc
on t1.cid=sc.cid
group by sc.sid
having count(distinct sc.cid)= (select count(distinct cid) from sc where sid = '01')
)t1
left join student
on t1.sid=student.sid
where t1.sid!='01'
-- 13. 把“SC”表中“张三”老师教的课的成绩都更改为此课程的平均成绩;
-- 暂跳过update题目
-- 14. 查询没学过"张三"老师讲授的任一门课程的学生姓名
select
sname
from student
where sid not in
(
select
distinct sid
from sc
left join course
on sc.cid=course.cid
left join teacher
on course.tid=teacher.tid
where tname='张三'
)
-- 15. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩
select
t1.sid,sname,avg_score
from
(
select
sid,count(if(score<60,cid,null)),avg(score) as avg_score
from sc
group by sid
having count(if(score<60,cid,null)) >=2
)t1
left join student
on t1.sid=student.sid
-- 16. 检索"01"课程分数小于60,按分数降序排列的学生信息
select
sid,if(cid='01',score,100)from sc
where if(cid='01',score,100)<60
order by if(cid='01',score,100) desc
-- 17. 按平均成绩从高到低显示所有学生的平均成绩
select sid,avg(score)
from sc
group by sid
order by avg(score) desc
-- 18. 查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率
select
sc.cid
,cname
,max(score) as max_score
,min(score) as min_score
,avg(score) as avg_score
,count(if(score>=60,sid,null))/count(sid) as pass_rate
from sc
left join course
on sc.cid=course.cid
group by sc.cid
-- 19. 按各科平均成绩从低到高和及格率的百分数从高到低顺序
#这里先按照平均成绩排序,再按照及格百分数排序,
select
cid
,avg(score) as avg_score
,count(if(score>=60,sid,null))/count(sid) as pass_rate
from sc
group by cid
order by avg_score,pass_rate desc
-- 20. 查询学生的总成绩并进行排名
select
sid
,sum(score) as sum_score
from sc
group by sid
order by sum_score desc
-- 21. 查询不同老师所教不同课程平均分从高到低显示
select
tid
,avg(score) as avg_score
from course
left join sc
on course.cid=sc.cid
group by tid
order by avg_score desc
-- 22. 查询所有课程的成绩第2名到第3名的学生信息及该课程成绩
select
sid,rank_num,score,cid
from
(
select
rank() over(partition by cid order by score desc) as rank_num
,sid
,score
,cid
from sc
)t
where rank_num in (2,3)
-- 23. 统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比
select
sc.cid
,cname
,count(if(score between 85 and 100,sid,null))/count(sid)
,count(if(score between 70 and 85,sid,null))/count(sid)
,count(if(score between 60 and 70,sid,null))/count(sid)
,count(if(score between 0 and 60,sid,null))/count(sid)
from sc
left join course
on sc.cid=course.cid
group by sc.cid,cname
-- 24. 查询学生平均成绩及其名次
select
sid
,avg_score
,rank() over (order by avg_score desc)
from
(
select
sid
,avg(score) as avg_score
from sc
group by sid
)t
-- 25. 查询各科成绩前三名的记录
select
sid,cid,rank1from
(
select
cid
,sid
,rank() over(partition by cid order by score desc) as rank1
from sc
)twhere rank1<=3
-- 26. 查询每门课程被选修的学生数
select
count(sid)
,cid
from sc
group by cid
-- 27. 查询出只选修了一门课程的全部学生的学号
select
sid
from sc
group by sid
having count(cid) =1
-- 28. 查询男生、女生人数
select
ssex
,count(distinct sid)
from student
group by ssex
-- 29. 查询名字中含有"风"字的学生信息
select
sid,sname
from student
where sname like '%风%'
-- 30. 查询同名同性学生名单,并统计同名人数
select
ssex
,sname
,count(sid)
from student
group by ssex,sname
having count(sid)>=2
-- 31. 查询1990年出生的学生名单(注:Student表中Sage列的类型是datetime)
select
sid,sname,sage
from student
where year(sage)=1990
-- 32. 查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列
select
cid,avg(score) as avg_score
from sc
group by cid
order by avg_score,cid desc
-- 33. 查询不及格的课程,并按课程号从大到小排列
select
cid,sid,score
from sc
where score<60
order by cid desc,sid
-- 34. 查询课程编号为"01"且课程成绩在60分以上的学生的学号和姓名;
select
sid,cid,score
from sc
where cid='01' and score>60
-- 35. 查询选修“张三”老师所授课程的学生中,成绩最高的学生姓名及其成绩
select
sc.sid,sname,cname,score
from sc
left join course
style="font-weight: 600;">=course.cid
left join teacher
style="font-weight: 600;">=teacher.tid
left join student
style="font-weight: 600;">=student.sid
where tname='张三'
order by score desc
limit 1;
-- 36. 查询每门功课成绩最好的前两名
select
cid,sid,rank1
from
(
select
cid
,sid
,rank() over(partition by cid order by score desc) as rank1
from sc
)t
where rank1 <=2
-- 37. 统计每门课程的学生选修人数(超过5人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列
select
cid
,count(sid) as cnt
from sc
group by cid
having cnt>=5
order by count(sid) desc,cid
-- 38. 检索至少选修两门课程的学生学号
select
sid
,count(cid)
from sc
group by sid
having count(cid)>=2
-- 39. 查询选修了全部课程的学生信息
select
sid
,count(cid)
from sc
group by sid
having count(cid)=(select count(distinct cid) from sc)
-- 40. 查询各学生的年龄
select
sid,sname,year(curdate())-year(sage) as sage
from student
-- 41. 查询本周过生日的学生
select
sid,sname,sage
from student
where weekofyear(sage)=weekofyear(curdate())
-- 42. 查询下周过生日的学生
select
sid,sname,sage
from student
where weekofyear(sage) = weekofyear(date_add(curdate(),interval 1 week))
-- 43 查询本月过生日的学生
select
sid,sname,sage
from student
where month(sage) = month(curdate())
-- 44. 查询下月过生日的学生
select
sid,sname,sage
from student
where month(date_sub(sage,interval 1 month)) = month(curdate())