# DQL查询语言
## 子查询
按照结果集的行列数不同,子查询可以分为以下几类:
- 标量子查询:结果集只有一行一列(单行子查询)
- 列子查询:结果集有一列多行
- 行子查询:结果集有一行多列
- 表子查询:结果集多行多列```sql
-- 查询比小虎年龄大的所有学生
-- 标量子查询
SELECT
*
FROM
student
WHERE
age > ( SELECT age FROM student WHERE NAME = '小虎' );
``````sql
-- 查询有一门学科分数大于90分的学生信息
-- 列子查询
SELECT
*
FROM
student
WHERE
id IN (
SELECT
s_id
FROM
scores
WHERE
score > 90);
``````sql
-- 查询男生且年龄最大的学生
-- 行子查询
SELECT
*
FROM
student
WHERE
age = (
SELECT
max( age )
FROM
student
GROUP BY
gender
HAVING
gender = '男'
)
-- 优化
SELECT
*
FROM
student
WHERE
( age, gender ) = (
SELECT
max( age ),
gender
FROM
student
GROUP BY
gender
HAVING
gender = '男'
)
```> 总结:
>
> - where型子查询,如果是where 列 = (内层sql),则内层的sql返回的必须是单行单列,单个值。
> - where型子查询,如果是where (列1,列2) = (内层sql),内层的sql返回的必须是单列,可以是多行。```sql
-- 取排名数学成绩前五的学生,正序排列
SELECT
*
FROM
(
SELECT
s.*,
sc.score score,
科目
FROM
student s
LEFT JOIN scores sc ON s.id = sc.s_id
LEFT JOIN course c ON = sc.c_id
WHERE
= '数学'
ORDER BY
score DESC
LIMIT 5
) t
WHERE
t.gender = '男';
```> 经验分享:
>
> 1. 分析需求
> 2. 拆步骤
> 3. 分步写sql
> 4. 整合拼装sql```sql
-- 查询每个老师的代课数
SELECT , ,( SELECT count(*) FROM course c WHERE = ) AS 代课的数量
FROM
teacher t;
----------------------------------------------------------------------------
SELECT
,
,
count(*) '代课的数量'
FROM
teacher t
LEFT JOIN course c ON c.t_id =
GROUP BY
,
;
``````sql
-- exists
SELECT
*
FROM
teacher t
WHERE
EXISTS ( SELECT * FROM course c WHERE c.t_id = );
----------------------------------------------------------------------------SELECT
t.*,
c.`name`
FROM
teacher t
INNER JOIN course c ON = c.t_id;
```> 总结:如果一个需求可以不用子查询,尽量不使用。
>
> `sql可读性太低。`除了一些理论知识的学习,今天还有大量的实训案例,来看一下今天的实训成果吧!
-- 1.查询'01'号学生的姓名和各科成绩 **
SELECT
s.id sid,
s.`name` sname,
c.`name` cname,
sc.score
FROM
student s
LEFT JOIN scores sc ON s.id = sc.s_id
LEFT JOIN course c ON = sc.c_id
WHERE
s.id = 1;
-- 2.查询各个学科的平均成绩和最高成绩**
SELECT
,
c.`name`,
AVG( sc.score ),
max( sc.score )
FROM
course c
LEFT JOIN scores sc ON = sc.c_id
GROUP BY
,
c.`name`;
-- 3.查询每个同学的最高成绩和科目名称
-- 4.查询所有姓张的同学的各科成绩**
SELECT
s.id,
s.`name`,
c.`name` cname,
sc.score
FROM
student s
LEFT JOIN scores sc ON sc.s_id = s.id
LEFT JOIN course c ON = sc.c_id
WHERE
s.`name` LIKE '张%';
-- 5.查询每个课程的最高分的学生信息
SELECT
*
FROM
student s
WHERE
id IN (
SELECT DISTINCT
r.s_id
FROM
(
SELECT
,
,
max( score ) score
FROM
student s
LEFT JOIN scores r ON r.s_id = s.id
LEFT JOIN course c ON = r.c_id
GROUP BY
,
) t
LEFT JOIN scores r ON r.c_id =
AND t.score = r.score
);
-- 6.查询名字中含有'张'或'李'字的学生的信息和各科成绩。
select
student.`name`,
scores.`score`,
course.`name`
FROM
student
LEFT JOIN scores ON studen = scores.s_id
LEFT JOIN course ON course.id = scores.c_id
where
studen = 1
and
studen LIKE '张%'
OR studen LIKE '李%';
-- 7.查询平均成绩及格的同学的信息。
SELECT
*
FROM
student
WHERE
id IN (
SELECT
sc.s_id
FROM
scores sc
GROUP BY
sc.s_id
HAVING
avg( sc.score ) >= 70
);
-- 8.将学生按照总分数进行排名。
SELECT
studen,student.`name`,SUM(scores.score) sum
FROM
student
LEFT JOIN scores on studen = scores.s_id
GROUP BY scores.s_id
ORDER BY sum DESC;
-- 9.查询数学成绩的最高分、最低分、平均分。
SELECT
course.`name`,MAX(scores.score),MIN(scores.score),avg(scores.score)
FROM
student
LEFT JOIN scores ON studen = scores.s_id
LEFT JOIN course ON course.id = scores.c_id
WHERE
= '数学';
-- 10.将各科目按照平均分排序。
SELECT
course.`name`,avg(scores.score) avg
FROM
scores
LEFT JOIN course ON course.id = scores.c_id
GROUP BY scores.c_id
ORDER BY avg DESC;
-- 11.查询老师的信息和他所带的科目的平均分
select
t.*,,,avg(sc.score)
from
teacher t
left join course c on =c.t_id
left join scores sc on sc.c_id=
group by
,;
-- 12.查询被"Tom"和"Jerry"教的课程的最高分和最低分
select
t.*,,,max(sc.score),min(sc.score)
from
teacher t
left join course c on =c.t_id
left join scores sc on sc.c_id=
group by
,
having
in ('Tom','Jerry');
-- 14.查询所有学生的课程及分数
SELECT
s.id,
,
,
,
r.score
FROM
student s
LEFT JOIN scores r ON s.id = r.s_id
LEFT JOIN course c ON = r.c_id;
-- 13.查询每个学生的最好成绩的科目名称
SELECT
,
t.sname,
r.c_id,
,
t.score
FROM
(
SELECT
s.id,
sname,
max( r.score ) score
FROM
student s
LEFT JOIN scores r ON r.s_id = s.id
GROUP BY
s.id,
) t
LEFT JOIN scores r ON r.s_id =
AND r.score = t.score
LEFT JOIN course c ON r.c_id = ;
-- 15.查询课程编号为1且课程成绩在60分以上的学生的学号和姓名
SELECT
*
FROM
student s
WHERE
s.id IN (
SELECT
r.s_id
FROM
scores r
WHERE
r.c_id = 1
AND r.score > 60);
SELECT
s.*,
r.*
FROM
student s
LEFT JOIN scores r ON s.id = r.s_id
WHERE
r.c_id = 1
AND r.score > 60;
-- 16. 查询平均成绩大于等于70的所有学生学号、姓名和平均成绩
select
,,avg(sc.score)
from
student stu
left join course c on =
left join scores sc on sc.s_id=sc.c_id
group by
,
having
avg(sc.score)>=70;
-- 17.查询有不及格课程的学生信息
select
stu.*,,sc.score
from
student stu
left join course c on =
left join scores sc on =sc.c_id
where
sc.score<60;
-- 18.查询每门课程有成绩的学生人数
select count() ,
from
( select
,
from
course c
left join scores sc on sc.c_id=
where
sc.score>0)t
left join course c on =
group by
,;
-- 19.查询每门课程的平均成绩,结果按照平均成绩降序排列,如果平均成绩相同,再按照课程编号升序排列
select
,,avg(sc.score)
from
course c
left join scores sc on sc.c_id=
group by
,
order by
avg(sc.score) desc,
asc;
-- 20.查询平均成绩大于60分的同学的学生编号和学生姓名和平均成绩
select
,,avg(sc.score)
from
student stu
left join course c on =
left join scores sc on sc.s_id=sc.c_id
group by
,
having
avg(sc.score)>60;
-- 21.查询有且仅有一门课程成绩在80分以上的学生信息
select
,
from
student stu
left join scores sc on =sc.s_id
where
sc.score>80
group by
,
having
count(*)=1;
-- 22.查询出只有三门课程的学生的学号和姓名
select
,
from
student stu
left join scores sc on =sc.s_id
group by
,
having
count(*)=3;
-- 23.查询有不及格课程的课程信息
select
,,sc.score
from
course c
left join scores sc on sc.c_id=
group by
,
having
min(sc.score)<60;
-- 24.查询至少选择4门课程的学生信息
SELECT
s.id,
FROM
student s
LEFT JOIN scores r ON s.id = r.s_id
GROUP BY
s.id,
HAVING
count(*) >= 4;
-- 25.查询没有选全所有课程的同学的信息
SELECT
*
FROM
student
WHERE
id IN (
SELECT
r.s_id
FROM
scores r
GROUP BY
r.s_id
HAVING
count(*) != 5
);
-- 26.查询选全所有课程的同学的信息
select
stu.*
from
student stu
left join course c on =
group by
,
having
(select count(id)from course)=5;
-- 27.查询各学生都选了多少门课
select
stu.*,count(*)
from
student stu
left join scores sc on =sc.s_id
group by
,;
-- 28.查询课程名称为"java",且分数低于60分的学生姓名和分数
select
,,sc.score
from
student stu
left join course c on =
left join scores sc on sc.c_id=
where
='java'
and
sc.score<60;
-- 29.查询学过"Tony"老师授课的同学的信息
select
stu.*
from
student stu
left join scores sc on sc.s_id =
left join course c on sc.c_id=
left join teacher t on c.t_id=
where
='Tony';
-- 30.查询没学过"Tony"老师授课的学生信息
SELECT
*
FROM
student
WHERE
id NOT IN (
SELECT DISTINCT
s.id
FROM
student s
LEFT JOIN scores r ON r.s_id = s.id
LEFT JOIN course c ON = r.c_id
LEFT JOIN teacher t ON = c.t_id
WHERE
= 'Tom'
);
-- 1根据学生学号 查询 2020年-1-1之后借过哪些书籍
select
stu.sid ,stu.sname,br.bdate
from
student1 stu
left join borrowrecored br on stu.cid=br.cid
left join book b on br.bid=b.bid
where
br.bdate>'2020-1-1';
-- 2根据书籍编号 查询2020-1-1之前都有那哪些学生借阅过
select
b.bid,b.bname,br.bdate,stu.sname
from
book b
left join borrowrecored br on b.bid=br.bid
left join student stu on br.bid=stu.sid
where
br.bdate<'2020-1-1';
-- 3根据学生编号查询该生一共借阅过多少本书
select
stu.sid,stu.sname,count(*)
from
student stu
left join borrowrecored br on br.bid=stu.sid
group by
stu.sid,stu.sname;
-- 4根据书籍编号查询书籍一共被借阅过多少次
select
b.bid,b.bname,count(*)
from
book b
left join borrowrecored br on br.bid=b.bid
group by
b.bid,b.bname;
-- 5根据学院名称查询该学院的学生一共借过哪些书籍
select
stu.sdepartment,b.bname,count(*)
from
student1 stu
left join book b on stu.sid=b.bid
left join borrowrecored br on b.bid=br.bid
group by
stu.sdepartment,b.bname;
-- 6查询哪个学生最爱看书
select
stu.sid,stu.sname ,count(*)
from
student stu
left join book b on stu.sid=b.bid
left join borrowrecored br on b.bid=br.bid
group by
stu.sid
order by
count(*) desc;
-- 7查询那本书最受欢迎
select
b.bid,b.bname,count(*)
from
book b
left join borrowrecored br on br.bid=b.bid
group by
b.bid,b.bname
order by
count(*) desc
















