学生表 成绩表 课程表 教师表

学生表:
Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别
课程表:
Course(c_id,c_name,t_id) – –课程编号, 课程名称, 教师编号
教师表:
Teacher(t_id,t_name) –教师编号,教师姓名
成绩表:
Score(s_id,c_id,s_s_score) –学生编号,课程编号,分数

根据以上信息按照下面要求写出对应的SQL语句。
ps:这些题考察SQL的编写能力,对于这类型的题目,需要你先把4张表之间的关联关系搞清楚了,最好的办法是自己在草稿纸上画关联图,然后再编写对应的SQL语句就比较容易了。

下图是我在草稿纸上画的这4张表的关系图,不好理解,你可以列举一些数据案例来辅助理解:

学生表 成绩表 课程表 教师表_第1张图片

案例数据建立参考如下
表名和字段
–1.学生表
Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别

–2.课程表
Course(c_id,c_name,t_id) – –课程编号, 课程名称, 教师编号

–3.教师表
Teacher(t_id,t_name) –教师编号,教师姓名

–4.成绩表
Score(s_id,c_id,s_score) –学生编号,课程编号,分数

建立数据库、建表和插入数据

题目:思路、关键函数、解题语句、结果

知识点

语句表

学生表 成绩表 课程表 教师表_第2张图片

建表和插入数据

新建数据库

数据库属性 utf8 -- UTF-8 Unicode

排序规则 utf8_unicode_ci

学生表 成绩表 课程表 教师表_第3张图片

建表(创建查询,复制下方语句到查询中,运行即可)

-- 学生表
-- Student(s_id,s_name,s_birth,s_sex)
-- 学生编号,学生姓名, 出生年月,学生性别
CREATE TABLE `Student`(
`s_id` VARCHAR(20),
`s_name` VARCHAR(20) NOT NULL DEFAULT '',
`s_birth` VARCHAR(20) NOT NULL DEFAULT '',
`s_sex` VARCHAR(10) NOT NULL DEFAULT '',
PRIMARY KEY(`s_id`)
);
-- 课程表
-- Course(c_id,c_name,t_id) 
-- 课程编号, 课程名称, 教师编号
CREATE TABLE `Course`(
`c_id` VARCHAR(20),
`c_name` VARCHAR(20) NOT NULL DEFAULT '',
`t_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`c_id`)
);
-- 教师表
-- Teacher(t_id,t_name)
-- 教师编号,教师姓名
CREATE TABLE `Teacher`(
`t_id` VARCHAR(20),
`t_name` VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY(`t_id`)
);
-- 成绩表
-- Score(s_id,c_id,s_s_score) 
-- 学生编号,课程编号,分数
CREATE TABLE `Score`(
`s_id` VARCHAR(20),
`c_id` VARCHAR(20),
`s_score` INT(3),
PRIMARY KEY(`s_id`,`c_id`)
)

插入数据(创建查询,复制下方语句到查询中,运行即可)

-- 学生表数据
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' , '女');
-- 教师表数据
insert into Teacher values('t01' , '张三');
insert into Teacher values('t02' , '李四');
insert into Teacher values('t03' , '王五');
-- 课程表数据
insert into Course values('01' , '语文' , '02');
insert into Course values('02' , '数学' , '01');
insert into Course values('03' , '英语' , '03');

-- 成绩表数据
insert into Score values('01' , '01' , 80);
insert into Score values('01' , '02' , 90);
insert into Score values('01' , '03' , 99);
insert into Score values('02' , '01' , 70);
insert into Score values('02' , '02' , 60);
insert into Score values('02' , '03' , 80);
insert into Score values('03' , '01' , 80);
insert into Score values('03' , '02' , 80);
insert into Score values('03' , '03' , 80);
insert into Score values('04' , '01' , 50);
insert into Score values('04' , '02' , 30);
insert into Score values('04' , '03' , 20);
insert into Score values('05' , '01' , 76);
insert into Score values('05' , '02' , 87);
insert into Score values('06' , '01' , 31);
insert into Score values('06' , '03' , 34);
insert into Score values('07' , '02' , 89);
insert into Score values('07' , '03' , 98);

 

学生表 成绩表 课程表 教师表_第4张图片

刷新‘表‘就能看见建立的表了

学生表 成绩表 课程表 教师表_第5张图片学生表 成绩表 课程表 教师表_第6张图片学生表 成绩表 课程表 教师表_第7张图片

题目

-- 1.查询课程编号为‘01’的课程比‘02’的课程成绩高的所有学生的学号、姓名和各自‘01’‘02’课程成绩

思路:通过学生编号将成绩表的课程‘01’成绩和课程‘02’成绩构建一张新表包含:学生编号、课程‘01’成绩、课程‘02成绩’

关键函数:SELECT...FROM...INNER JOIN...ON...WHERE...

解题语句:

SELECT a.s_id ,c.s_name,a.s_score '01',b.s_score '02'FROM
(SELECT s_id,c_id,s_score FROM score WHERE c_id='01')AS a
INNER JOIN
(SELECT s_id,c_id,s_score FROM score WHERE c_id='02')AS b ON a.s_id=b.s_id
INNER JOIN student AS c ON a.s_id=c.s_id
WHERE a.s_score>b.s_score;

结果:

学生表 成绩表 课程表 教师表_第8张图片

-- 2、查询平均成绩大于60分的学生的学号和平均成绩

思路:以学生学号进行分组,算平均成绩,筛选输出平均成绩大于60分的学生学号和平均成绩

关键函数:GROUP BY、 AVG()

解题语句

SELECT s_id,AVG(s_score)
FROM score
GROUP BY s_id HAVING AVG(s_score)>60

结果:

学生表 成绩表 课程表 教师表_第9张图片

-- 3、查询所有学生的学号、姓名、选课数、总成绩

思路:学生表通过学生学号左关联成绩表,以学生学号进行分组,count函数计算选课数,sum函数计算总成绩,ifnull函数将由于左关联产生的成绩表中没有的同学数据null变成0

关键函数:GROUP BY、COUNT()、SUM()、IFNULL( , )、LEFT JOIN

解题语句

SELECT a.s_id,a.s_name,COUNT(b.c_id),SUM(IFNULL(b.s_score,0))
FROM student AS a
LEFT JOIN score AS b
ON a.s_id=b.s_id
GROUP BY s_id

结果:

学生表 成绩表 课程表 教师表_第10张图片

-- 4、查询姓“张”的老师的个数

思路:用like筛选老师姓名,避免姓名重复通过计算老师id来计算个数

关键函数:LIKE、COUNT

解题语句

SELECT COUNT(t_id)    
FROM teacher
WHERE t_name LIKE '张%'

结果:

学生表 成绩表 课程表 教师表_第11张图片

-- 5、查询没学过“张三”老师课的学生的学号、姓名

思路1:多层嵌套、子查询

通过教师表查询得姓名为‘张三’的教师编号,用老师编号在课程表查询该老师教授的课程编号,通过课程编号在成绩表中查询没有该课程成绩的学生编号,最后通过学生编号在学生表中得出这些同学的学号姓名

关键函数:where、in

解题语句1

SELECT s_id,s_name FROM student  
WHERE s_id NOT IN(
SELECT s_id FROM score
WHERE c_id =
(SELECT c_id FROM course
WHERE t_id=
(SELECT t_id FROM teacher
WHERE t_name = '张三')))

结果:

学生表 成绩表 课程表 教师表_第12张图片

思路2:成绩和课程表通过课程编号内连接,再与学生成绩表通过学生编号进行内连接。筛选处有‘张三’的课程成绩的学生编号,在学生表中选出学生编号不在上面选中的学生编号的学生姓名编号和姓名

关键函数:inner jion 、not in

解题语句2

SELECT s_id,s_name FROM student
WHERE s_id NOT IN(
SELECT a.s_id FROM score AS a
INNER JOIN course AS c ON c.c_id=a.c_id
INNER JOIN teacher AS d ON d.t_id=c.t_id
WHERE d.t_name='张三')

结果:

学生表 成绩表 课程表 教师表_第13张图片

-- 6、查询学过“张三”老师所教的所有课的同学的学号、姓名

理解1:学过张三老师的课的学生信息

思路:构建一张表包含:学生学号、学生姓名、课程成绩、课程老师。再通过老师姓名筛选

用分组去重(虽然本题没有重复结果)

关键函数:inner jion

解题语句

SELECT st.s_id,st.s_name FROM student AS st 
INNER JOIN score AS s ON st.s_id=s.s_id
INNER JOIN course AS c ON s.c_id=c.c_id
INNER JOIN teacher AS t ON t.t_id=c.t_id
WHERE t.t_name ='张三'
GROUP BY st.s_id

结果:

学生表 成绩表 课程表 教师表_第14张图片

理解2:学了张三老师所有课的学生信息

思路:构建一张表包含:学生学号、学生姓名、课程成绩、课程老师。通过老师姓名筛选。再选出学生所选课程数等于张三老师所教的课程数的学生信息

解题语句

SELECT st.s_id,st.s_name FROM student AS st 
INNER JOIN score AS s ON st.s_id=s.s_id
INNER JOIN course AS c ON s.c_id=c.c_id
INNER JOIN teacher AS t ON t.t_id=c.t_id
WHERE t.t_name ='张三' 
GROUP BY st.s_id
HAVING
COUNT(st.s_id) IN
(SELECT COUNT(c_name) FROM course 
INNER JOIN teacher 
ON course.t_id=teacher.t_id 
WHERE teacher.t_name='张三')

结果:

学生表 成绩表 课程表 教师表_第15张图片

-- 7、查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名

思路1:通过内连接将成绩表课程‘01’和课程‘02’的信息相连接得出新表,从学生表中获取学生编号在新表中的学生标号和姓名

关键函数:inner jion、in

解题语句1

SELECT s_id,s_name FROM student
WHERE s_id IN
(
SELECT a.s_id FROM
(SELECT s_id FROM score WHERE c_id='01')AS a
INNER JOIN
(SELECT s_id FROM score WHERE c_id='02')AS b
ON a.s_id=b.s_id
)

结果:

学生表 成绩表 课程表 教师表_第16张图片

思路2:在学生表中选出满足两个条件的学生学号和学生姓名,条件1:有课程编号‘01’成绩的学生编号,条件2:有课程编号‘02’成绩的学生编号

关键函数:WHERE...IN...AND

解题语句2

SELECT s_id,s_name FROM student
WHERE s_id IN 
(SELECT s_id FROM score WHERE c_id='01')
AND s_id IN 
(SELECT s_id FROM score WHERE c_id='02')

结果:

学生表 成绩表 课程表 教师表_第17张图片

-- 8、查询各门的总成绩、平均成绩和人数

关键函数:sum、avg、count

解题语句

SELECT c_id '课程编号',SUM(s_score) '总成绩',
AVG(s_score ) '平均成绩',COUNT(s_score) '人数'
FROM score 
GROUP BY c_id

结果:

学生表 成绩表 课程表 教师表_第18张图片

-- 9、查询所有课程成绩小于60分的学生的学号、姓名

思路:得出各同学课程成绩小于60分的课程数,统计各同学共学了几门课,选出二者相等的学生学号、姓名

关键函数:group_by、inner jion

解题语句

SELECT a.s_id,t.s_name FROM
(
SELECT s_id,COUNT(c_id) 'count'
FROM score
WHERE s_score<60
GROUP BY s_id
)AS a
INNER JOIN
(
SELECT s_id,COUNT(c_id) 'count'
FROM score
GROUP BY s_id
)AS b ON a.s_id=b.s_id
INNER JOIN student AS t ON a.s_id=t.s_id
WHERE a.count=b.count

结果:

学生表 成绩表 课程表 教师表_第19张图片

-- 10、查询没有学全所有课的学生的学号、姓名

思路:将学生与成绩表通过学生学号左连接,计算每个学生的成绩数,选出小于课程总数的学生学号和姓名

关键函数:group_by、count、distinct、left jion

解题语句

SELECT st.s_id '学生学号',st.s_name '学生姓名'
FROM student AS st
LEFT JOIN score AS sc ON st.s_id=sc.s_id
GROUP BY st.s_id 
HAVING COUNT(DISTINCT sc.c_id)<(SELECT count(DISTINCT c_id) FROM course)

结果:

学生表 成绩表 课程表 教师表_第20张图片

-- 11、查询至少有一门课程与学号为“01”的学生所学课程相同的其他同学的学号

思路:选出课程与‘01’学生学过的课程相同的学生学号,去重,去掉‘01’同学

关键函数:in、and

解题语句

SELECT s_id,s_name FROM student 
WHERE s_id in
(
SELECT DISTINCT s_id FROM score 
WHERE c_id in
(
SELECT c_id FROM score WHERE s_id='01'
)
AND s_id!='01'
)

结果:

学生表 成绩表 课程表 教师表_第21张图片

-- 12、查询和“01”号同学所学课程完全相同的其他同学的学号

思路1:将学号不为‘01’的学生课程编号连接形成新的字段,选出与学号为‘01’的学生课程编号连接形成字段相同的学生学号

关键函数:group_concat、group by

解题语句1

SELECT s_id FROM score
WHERE s_id <>'01'
GROUP BY s_id
HAVING GROUP_CONCAT(c_id)=(
SELECT GROUP_CONCAT(c_id) FROM score WHERE s_id='01')

结果:

学生表 成绩表 课程表 教师表_第22张图片

思路2:将学号不为‘01’的学生成绩表左连接学号为‘01’的学生成绩表,计算每一个学号不为‘01’的学生课程数,选出课程数和‘01’学生相同的学生学号

关键函数:left jion、group_by、count

解题语句

SELECT a.s_id FROM
(SELECT * FROM score WHERE s_id!='01') AS a
LEFT JOIN(SELECT * FROM score WHERE s_id='01')AS b
ON a.c_id=b.c_id
GROUP BY a.s_id
HAVING COUNT(b.s_id)=(SELECT COUNT(c_id) FROM score WHERE s_id='01') 

结果:

学生表 成绩表 课程表 教师表_第23张图片

-- 15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩

思路:成绩表和学生表通过学生学号关联得,查询学号满足以下:选出成绩表中小于60分的成绩,再通过学生学号分组,最后选出此表中大于一门成绩的学生生学号。

关键函数:AVG,INNER JOIN ,GROUP BY,COUNT

解题语句

SELECT a.s_id,a.s_name,AVG(b.s_score) FROM student AS a
INNER JOIN score AS b
ON a.s_id=b.s_id
WHERE a.s_id IN
(SELECT s_id FROM score AS a 
WHERE s_score<60
GROUP BY s_id
HAVING COUNT(s_score)>1)
GROUP BY a.s_id

结果:

学生表 成绩表 课程表 教师表_第24张图片

-- 16、检索"01"课程分数小于60,按分数降序排列的学生信息

思路:学生表和成绩表通过学生学号链接,用课程编号为‘01’和课程成绩小于60两个条件筛选,最后通过分数降序

关键函数:INNER JOIN,ORDER BY , DESC

解题语句

SELECT * FROM student AS a
INNER JOIN score AS b ON a.s_id=b.s_id
WHERE b.c_id='01'
AND b.s_score<60
ORDER BY b.s_score DESC

结果:

学生表 成绩表 课程表 教师表_第25张图片

-- 17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

思路:用avg计算平均成绩,按照学生学号进行分组排序,利用max来显示每一门课的成绩(max函数没有实际意义,只是用来显示),用case when(课程编号为‘01’,输出成绩,否则输出null)得到每一门的课程成绩

关键函数:GROUP BY、ORDER BY、CASE WHEN THEN ELSE

解题语句

SELECT 
s_id,
MAX(CASE WHEN c_id='01' THEN s_score ELSE NULL END)'01',
MAX(CASE WHEN c_id='03' THEN s_score ELSE NULL END)'02',
MAX(CASE WHEN c_id='02' THEN s_score ELSE NULL END)'03',
AVG(s_score) 
FROM score
GROUP BY s_id
ORDER BY AVG(s_score) DESC

结果:

学生表 成绩表 课程表 教师表_第26张图片

-- 18、查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率

-- 及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90

思路:课程表和成绩表通过课程编号链接,通过课程编号分组,取出课程编号、课程名、最高分、最低分和平均分。将是否满足条件的分数通过case when函数变成01变量,求和便是符合条件的学生数,除以参与这一门考试的学生总数,便是各个分数段的概率

关键函数:group by,sum,case when ,count,max,min,avg,inner jion

解题语句:

SELECT b.c_id,b.c_name,
MAX(a.s_score)'最高分',MIN(a.s_score)'最低分',AVG(a.s_score)'平均分',
SUM(CASE WHEN a.s_score>=60 THEN 1 ELSE 0 END)/COUNT(a.s_id)'及格率',
SUM(CASE WHEN a.s_score>=70 AND a.s_score<80 THEN 1 ELSE 0 END)/COUNT(a.s_id)'中等率',
SUM(CASE WHEN a.s_score>=80 AND a.s_score<90 THEN 1 ELSE 0 END)/COUNT(a.s_id)'优良率',
SUM(CASE WHEN a.s_score>=90 THEN 1 ELSE 0 END)/COUNT(a.s_score)'优秀率'
FROM score AS a
INNER JOIN course AS b ON a.c_id=b.c_id
GROUP BY a.c_id

结果:

学生表 成绩表 课程表 教师表_第27张图片

-- 19、按各科成绩进行排序,并显示排名

关键函数:rank()

解题语句:

SELECT s_score,rank() over(PARTITION by s_id ORDER BY s_score DESC) FROM score;

-- 20、查询学生的总成绩并进行排名

关键函数:sum、group by、order by

解题语句:

SELECT *,SUM(s_score) FROM score 
GROUP BY s_id 
ORDER BY SUM(s_score) DESC

结果:

学生表 成绩表 课程表 教师表_第28张图片

-- 21 、查询不同老师所教不同课程平均分从高到低显示

思路:成绩表通过课程编号和课程表进行连接为了获得课程名,再通过老师编号和教师表进行连接为了获得老师名,通过课程编号或者课程名字进行分组,输出课程编号、课程名、教师名、平均分,最后按照平均分排序

关键函数:avg、INNER JOIN、GROUP BY、ORDER BY

解题语句:

SELECT a.c_id,b.c_name,c.t_name,AVG(a.s_score) FROM score AS a
INNER JOIN course AS b ON a.c_id=b.c_id
INNER JOIN teacher AS c ON b.t_id=c.t_id 
GROUP BY a.c_id
ORDER BY AVG(a.s_score) DESC

结果:

学生表 成绩表 课程表 教师表_第29张图片

-- 22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩

思路:学生表和成绩表通过课程编号相连接,通过row_number函数增加一列课程成绩在该课程的排名,最后通过子查询筛选出排名,即增加的排名列数字为2,3的数据

关键函数:row_number、ORDER BY、INNER JOIN

解题语句:

SELECT * FROM 
(
SELECT b.s_id,b.s_name,b.s_birth,,b.s_sex,a.c_id,a.s_score,
row_number()over(PARTITION by a.c_id ORDER BY a.s_score DESC) m
FROM score AS a INNER JOIN student AS b ON a.s_id=b.s_id )
WHERE m IN(2,3)

-- 23、使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计各分数段人数:课程ID和课程名称

思路:通过课程编号将成绩表和课程表连接,再通过课程编号分组,得出课程成绩和课程编号,通过case when函数将每个分数段的人数转换为0/1或者1/null 形式,通过sum(0/1)或者count(1/null)得出每个分数段的人数

关键函数:SUM/COUNT、case when、inner jion

解题语句:

SELECT a.c_id,b.c_name,
SUM(CASE WHEN a.s_score<60 THEN 1 ELSE 0 END) '不及格',
SUM(CASE WHEN a.s_score>=60 AND a.s_score<70 THEN 1 ELSE 0 END) '及格',
COUNT(CASE WHEN a.s_score>=70 AND a.s_score<85  THEN 1 ELSE NULL END) '良',
COUNT(CASE WHEN a.s_score>=85 THEN 1 ELSE NULL END) '优'
FROM score AS a
INNER JOIN course AS b ON a.c_id=b.c_id
GROUP BY a.c_id

结果:

学生表 成绩表 课程表 教师表_第30张图片

-- 24、查询学生平均成绩及其名次

关键函数:rank

解题语句:

SELECT s_id,AVG(s_score),rank() over(PARTITION by s_id ORDER BY AVG(s_score)DESC) FROM score

-- 25、查询各科成绩前三名的记录(不考虑成绩并列情况)

思路:学生表和成绩表通过课程编号相连接,通过row_number函数增加一列课程成绩在该课程的排名,最后通过子查询筛选出排名,即增加的排名列数字为1,2,3的数据

关键函数:row_number、ORDER BY、INNER JOIN

解题语句:

SELECT *
FROM (SELECT b.s_id,b.s_name,b.s_birth,,b.s_sex,a.c_id,a.s_score,
row_number()over(PARTITION by a.c_id ORDER BY a.s_score DESC) m
FROM score AS a INNER JOIN student AS b ON a.s_id=b.s_id ) a
WHERE m IN(1,2,3)

-- 26、查询每门课程被选修的学生数

解题语句:

SELECT c_id,COUNT(c_id) FROM score
GROUP BY c_id

结果:

学生表 成绩表 课程表 教师表_第31张图片

-- 27、查询出只有两门课程的全部学生的学号和姓名

思路1:通过学生学号将成绩表和学生表连接,通过学生学号分组,计算学生选课成绩的数量,用having筛选出数量为2的信息,输出学生学号和姓名

关键函数:LEFT JOIN、GROUP BY、HAVING、COUNT

解题语句1:

SELECT a.s_id,b.s_name,COUNT(a.c_id) FROM score AS a
LEFT JOIN student AS b ON a.s_id=b.s_id
GROUP BY a.s_id
HAVING COUNT(a.c_id)=2

结果:

学生表 成绩表 课程表 教师表_第32张图片

思路2:成绩表通过学生学号分组,选出选课成绩为2的学生学号;通过子查询,在学生表中去的学生学号和姓名

关键函数:GROUP BY

解题语句2:

SELECT s_id,s_name FROM student
WHERE s_id IN(
(SELECT s_id FROM score
GROUP BY s_id
HAVING COUNT(c_id)=2)
)

结果:

学生表 成绩表 课程表 教师表_第33张图片

-- 28、查询男生、女生人数

思路1:通过性别进行分组,计算每个性别人数

关键函数:GROUP BY、count

解题语句:

SELECT s_sex,COUNT(s_sex) 
FROM student 
GROUP BY s_sex

结果:

学生表 成绩表 课程表 教师表_第34张图片

思路2:将性别变成01变量,通过sum/count得出每个性别人数

关键函数:case when、count、sum

解题语句:

SELECT 
SUM(CASE WHEN s_sex='男' THEN 1 ELSE 0 END)'男生个数',
count(CASE WHEN s_sex='女' THEN 1 ELSE NULL END) '女生个数'
FROM student

结果:

学生表 成绩表 课程表 教师表_第35张图片

 

-- 29 查询名字中含有"风"字的学生信息

思路:用like进行字符串匹配

关键函数:like

解题语句:

SELECT * FROM student 
WHERE s_name LIKE '%风%'

结果:

学生表 成绩表 课程表 教师表_第36张图片

 

-- 31、查询1990年出生的学生名单

思路1:用like进行字符串匹配的方法得到出生日期为1990年

关键函数:like

解题语句:

SELECT * FROM student 
WHERE s_birth LIKE '1990%'

结果:

学生表 成绩表 课程表 教师表_第37张图片

思路2:用year函数去除日期中的年份,筛选出1990年的数据

关键函数:year

解题语句:

SELECT * FROM student
WHERE YEAR(s_birth)=1990

结果:

学生表 成绩表 课程表 教师表_第38张图片

-- 32、查询平均成绩大于等于85的所有学生的学号、姓名和平均成绩

关键函数:INNER JOIN...ON、GROUP BY...HAVING

解题语句:

SELECT a.s_id,a.s_name,AVG(b.s_score) FROM student AS a
INNER JOIN score AS b ON a.s_id=b.s_id
GROUP BY b.s_id
HAVING AVG(b.s_score)>=85

结果:

学生表 成绩表 课程表 教师表_第39张图片

-- 33、查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列

关键函数:avg、select...from...group by...order by ...,...

解题语句:

SELECT c_id,AVG(s_score)
FROM score
GROUP BY c_id
ORDER BY AVG(s_score),c_id DESC

结果:

学生表 成绩表 课程表 教师表_第40张图片

-- 34、查询课程名称为"数学",且分数低于60的学生姓名和分数

思路:将学生表(需要学生姓名)、成绩表(需要数学成绩)、课程表(需要课程名)连接起来筛选即可

关键函数:left jion....on

解题语句:

SELECT a.s_name,b.s_score FROM student AS a
LEFT JOIN score AS b
ON a.s_id=b.s_id
LEFT JOIN course AS c
ON b.c_id=c.c_id
WHERE c.c_name='数学'
AND b.s_score<60

结果:

学生表 成绩表 课程表 教师表_第41张图片

 

-- 35、查询所有学生的课程及分数情况

思路1:需要形成的新表包括学生学号、学生姓名、各科成绩。将学生表左连接各科成绩表,各科成绩表通过将成绩表和课程表用课程编号连接后用课程名筛选后得出

关键函数:SELECT... FROM...LEFT JOIN...ON...

解题语句1:

SELECT a.s_id'学号',a.s_name'姓名',d.s_score'语文',e.s_score'数学',f.s_score'英语' 
FROM student AS a
LEFT JOIN
(SELECT b.s_id,c.c_name,b.s_score FROM score AS b
LEFT JOIN course AS c ON b.c_id=c.c_id WHERE c_name='语文')AS d
ON a.s_id=d.s_id
LEFT JOIN
(SELECT b.s_id,c.c_name,b.s_score FROM score AS b
LEFT JOIN course AS c ON b.c_id=c.c_id WHERE c_name='数学')AS e
ON a.s_id=e.s_id
LEFT JOIN
(SELECT b.s_id,c.c_name,b.s_score FROM score AS b
LEFT JOIN course AS c ON b.c_id=c.c_id WHERE c_name='英语')AS f
ON a.s_id=f.s_id

结果:

学生表 成绩表 课程表 教师表_第42张图片

思路2:成绩表通过学生编号和学生表连接再通过课程编号和课程表连接,通过学生编号进行分组,通过case when输出各科成绩,判断课程名称并输出,由于输出只会输出第一条判断情况,所以用sum或者max

关键函数:MAX(CASE WHEN...THEN...ELSE NULL END)、SELECT... FROM...INNER JOIN...ON...

解题语句2:

SELECT c.s_id,c.s_name,
MAX(CASE WHEN b.c_name='语文' THEN a.s_score ELSE NULL END)'语文',
MAX(CASE WHEN b.c_name='数学' THEN a.s_score ELSE NULL END)'数学',
MAX(CASE WHEN b.c_name='英语' THEN a.s_score ELSE NULL END)'英语' 
FROM score AS a
INNER JOIN course AS b ON a.c_id=b.c_id
INNER JOIN student AS c ON a.s_id=c.s_id
GROUP BY c.s_id

结果:

学生表 成绩表 课程表 教师表_第43张图片

-- 36、查询课程成绩在70分以上的学生姓名、课程名称和分数

思路:将学生表成绩表课程表相连接

关键函数:SELECT... FROM...LEFT JOIN...ON...WHERE...

解题语句:

SELECT a.s_name,c.c_name,b.s_score FROM student AS a
LEFT JOIN score AS b ON a.s_id=b.s_id
LEFT JOIN course AS c ON b.c_id=c.c_id 
WHERE b.s_score>70

结果:

学生表 成绩表 课程表 教师表_第44张图片

-- 37、查询不及格的课程并按课程号从大到小排列

关键函数:SELECT... FROM...INNER JOIN...ON...WHERE...ORDER BY...DESC

解题语句:

SELECT a.s_id,b.s_name,a.c_id,a.s_score FROM score AS a
INNER JOIN student AS b
ON a.s_id=b.s_id
WHERE a.s_score<60
ORDER BY a.c_id DESC

结果:

学生表 成绩表 课程表 教师表_第45张图片

-- 38、查询课程编号为03且课程成绩在80分以上的学生的学号和姓名

关键函数:SELECT... FROM...INNER JOIN...ON...WHERE...AND...

解题语句:

SELECT a.s_id,b.s_name,a.s_score FROM score AS a
INNER JOIN student AS b
ON a.s_id=b.s_id
WHERE a.s_score>80
AND a.c_id='03'

结果:

学生表 成绩表 课程表 教师表_第46张图片

-- 39、求每门课程的学生人数

解题语句:

SELECT c_id,COUNT(s_score) FROM score
GROUP BY c_id

结果:

学生表 成绩表 课程表 教师表_第47张图片

-- 40、查询选修“张三”老师所授课程的学生中成绩最高的学生姓名及其成绩

思路:用窗口函数,rank

 

-- 41.查询不同课程成绩相同的学生的学生编号、课程编号、学生成绩

思路:从成绩表中通过用学生学号分组计算课程成绩数来选出至少学了有两门课的学生与成绩表内连接再通过学生学号和成绩分组筛选只有一个数据的学生学号

关键函数:INNER JOIN、GROUP BY、HAVING、COUNT(DISTINCT ...)

解题语句:

SELECT s_id FROM
(SELECT a.s_id,a.s_score FROM score AS a
INNER JOIN
(SELECT s_id FROM score
GROUP BY s_id HAVING COUNT(DISTINCT c_id)>1)AS b
ON a.s_id=b.s_id
GROUP BY a.s_id,a.s_score
)AS c
GROUP BY s_id HAVING COUNT(s_id)=1

结果:

学生表 成绩表 课程表 教师表_第48张图片

-- 43、统计每门课程的学生选修人数(超过5人的课程才统计)。

-- 要求输出课程号和选修人数,查询结果按人数降序排列,若人数相同,按课程号升序排列

关键函数:COUNT()、GROUP BY、HAVING、ORDER BY

解题语句:

SELECT c_id,COUNT(s_score) FROM score
GROUP BY c_id
HAVING COUNT(s_score)>5
ORDER BY COUNT(s_score) DESC,c_id

结果:

学生表 成绩表 课程表 教师表_第49张图片

-- 44、检索至少选修两门课程的学生学号和选课数

关键函数:COUNT()、GROUP BY、HAVING

解题语句:

SELECT s_id,COUNT(s_score) FROM score
GROUP BY s_id
HAVING COUNT(s_score)>=2

结果:

学生表 成绩表 课程表 教师表_第50张图片

-- 45、 查询选修了全部课程的学生信息

思路:由于要获得学生信息就通过学生学号将学生表和成绩表连接,将新表通过学生学号进行分组,筛选条件为学生课程数等于课程表中的课程数

关键函数:LEFT JOIN、GROUP BY、COUNT(DISTINCT ...)

解题语句:

SELECT * FROM student AS a
LEFT JOIN score AS b
ON a.s_id=b.s_id
GROUP BY a.s_id
HAVING COUNT(DISTINCT c_id) =( SELECT COUNT(c_id) FROM course)

结果:

学生表 成绩表 课程表 教师表_第51张图片

-- 46、查询各学生的年龄(精确到月份)

关键函数:DATEDIFF()

解题语句:

SELECT s_id,s_birth,DATEDIFF('2020-5-20',s_birth)/365 FROM student

结果:

学生表 成绩表 课程表 教师表_第52张图片

 

-- 50、查询下个月过生日的学生

思路:用now()获得现在的时间month取出现在的月份,生日的月份等于通过round取余数加一则是下周过生日

关键函数:=MONTH()、date()、NOW()、%

解题语句:

SELECT * FROM student WHERE 
MONTH(s_birth)=MONTH(date(NOW()))%12+1

结果:

学生表 成绩表 课程表 教师表_第53张图片


知识点:

1.inner jion、right jion、left jion的区别

inner join为“有效的连接”,就是根据on后面的关联条件,两张表中都有的数据才会显示

left join为主表全显示,连接后的表看on后面的选择条件,left join后面的条件,并不会影响左表的数据显示,左表数据会全部显示出来,连接的表如果没有数据,则全部显示为null

right join为“主表看on,后表全显”(右表数据不受影响),即右表数据全部显示,主表数据看on后面的选择条件

 

2.字符匹配

_代表一个字符, %代表0个及以上字符

开头是m m%

结尾是m %m

第二个字母为m _m%

非首字母字母有m _%m%

 

3.rank,dense_rankrow_number的区别

rank(跳跃排序)

分数 排名

92 1

82 2

82 2

67 4

dense_rank(连续排序)

分数 排名

92 1

82 2

82 2

67 3

row_number(无重复值排序)

分数 排名

92 1

82 2

82 3

67 4

 


语句表:

1、插入数据:

insert into 表名 values( ) #输入的值要跟原表对应

insert into Teacher values('02' , '李四')

 

2、查询表中的数据:

select * from 表名 # *号代表取全部列的数据

select * from student

 

select 指定列 from 表名

SELECT t_id,s_score FROM score

 

查询表中数据的统计量:min、max、avg、count、sum,

select avg(列名) from 表名

SELECT c_id '课程编号',SUM(s_score) '总成绩',AVG(s_score ) '平均成绩',COUNT(s_score) '人数' FROM score

GROUP BY c_id

 

条件查询:

select 指定列 from 表名 where 条件

SELECT s_id FROM score WHERE s_id <>'01'

条件符号:

(1)>大于 ;<小于; =等于; <>和!=不等于

(2)like 字符匹配 select * from teacher where t_name like '张%'

(3)between...and 区间 SELECT * FROM score WHERE s_score BETWEEN 70 AND 90

(4)in 指定数据集作为条件,也常用于子查询

 

3、GROUP BY 语句

根据一个或多个列对结果集进行分组,分组后的输出的统计量是每一组的统计量

SELECT 列名或统计量 FROM 表名 GROUP BY 列名

SELECT c_id,SUM(s_score),AVG(s_score ),COUNT(s_score)

FROM score

GROUP BY c_id

 

GROUP BY后的条件查询用having

 

4、ORDER BY 语句

排序

SELECT *,SUM(s_score) FROM score GROUP BY s_id ORDER BY SUM(s_score) DESC

 

5、year、month、day、now语句

用来从日期中提取需要的年/月/日

SELECT * FROM student WHERE YEAR(s_birth)=1990;

SELECT * FROM student WHERE MONTH(s_birth)=01;

SELECT * FROM student WHERE DAY(s_birth)='01';

条件可以用数字或者字符串

日期类型可以是YYYY-MM-DD、YYYYMMDD、YYYY/MM/DD

2020-05-20、20200520、2020/05/20

注意:对于YYYYMMDD这种格式日期,0不能少,一月份必须是01不能是1,但年份可以是后两位,即格式为YYMMDD

now()

获得当前时间有时分秒

 

6、LIMIT语句

用于选取第几行数据,SQL从0开始计数

SELECT c_id FROM score

LIMIT 0,1 #表示从0开始(第一行开始),选取第一行数据

 

7、DATEDIFF语句

用于计算日期间隔

SELECT s_id,s_birth,DATEDIFF('2020-5-20',s_birth)/365 FROM student

 

 

你可能感兴趣的:(postgreSQL,SQL)