周末杂谈:在MYSQL中,添加数据行后,使用右外连接查询所有课程的选修情况,要求列出课程编号、课程名称、选修人数,表中没有的课程列值为空的解决方法
实验前期准备
course表(课程表)
在其中:
cno(课程号)cname(课程名称)ccredit(学分)cdept(开课院系)
sc表(选修表)
在其中:
sno(学号)cno(课程号)grade(成绩)
题目详解
为sc表添加数据行:学号为1002、课程编号为10006、分数为76。使用右外连接查询所有课程的选修情况,要求列出课程编号、课程名称、选修人数,表中没有的课程列值为空。
我们可以分两步来解析这道题:
第一步
为sc表添加数据行:学号为1002、课程编号为10006、分数为76
这一步还是比较简单的,使用DML(数据操作语言)来解决即可。我们使用INSERT INTO来给指定字段添加数据。
INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);
值得注意的是:
• 插入数据时,指定的字段顺序需要与值的顺序是一一对应的。
• 字符串和日期型数据应该包含在引号中。
• 插入的数据大小,应该在字段的规定范围内。
依据以上,我们可以写出第一步的代码了。
insert into sc values ('1002','160006',76);
第二步
使用右外连接查询所有课程的选修情况,要求列出课程编号、课程名称、选修人数,表中没有的课程列值为空。
这一步就开始困难了,我们依旧是分三点来攻破。
1、列出课程编号、课程名称、选修人数
这一点是让我们从sc表中拿出“课程编号、课程名称、选修人数”,因此我们只要使用下面的命令,就能实现这条命令了。
select ‘课程表’.cno,cname,count(*) from sc
2、使用右外连接查询所有课程的选修情况
扩展:那什么是外连接呢?右外连接又是什么呢?
外连接是合并具有同一列的两个以上的表的行,结果集中除了包含一个表与另一个表匹配的行之外,还查询到了左表或右表中不匹配的行。
我们知道,在外连接中,两张表有主次关系,一主一次。
右外连接简称右连接,右连接刚好和左连接相反,返回右表的全部记录及左表中符合条件的记录,左表没有匹配的记录用 null 补全。
而右外连接表示 将join关键字右边的这张表看成主表**,**主要是为了将这张表的数据全部查询出来,顺便关联查询左边的表。
由此我们可以写出:
right join course c on c.cno=grade.cno
在这里,c是一个表的别名,它代表着course表。我们的这个语句使用了一个RIGHT JOIN,它会返回grade表中所有的记录和course表中匹配的记录,如果grade表中的记录在course表中没有匹配的记录,那么course表中的相关字段将被设置为NULL。
使用c作为course表的别名,可以方便地引用该表的字段,同时也使SQL语句更易于理解和阅读。
值得注意的是:
在MySQL中,如果你将语句 right join course c on c.cno=grade.cno 中的 c 改为 course,会导致语法错误,因为 course 不是一个有效的表别名或表名,哪怕你在MySQL中已经有一个名为 course 的表,依然会导致语法错误。这是因为在 right join 语句中,你必须为要连接的表提供唯一的表别名或表名,以便 MySQL 能够正确识别它们。
如果你想在 right join 语句中引用已经存在的 course 表,你可以选择另一个不同的表别名,例如:
SELECT *
FROM grade
RIGHT JOIN course c
ON c.cno = grade.cno;
这将使用表别名 c 来引用 course 表,从而避免与已经存在的 course 表名称冲突的问题。
3、对结果进行分组,并返回聚合数据
在MySQL中,GROUP BY
语句用于根据一个或多个列对结果集进行分组。这个语句将返回按指定列进行分组的聚合数据,例如计算每个组中行的总数、平均值、最大值等。
在下面这个语句中,c.cno
和c.cname
表示按照表c
中的两个列进行分组。这意味着查询将按照这两个列的值对结果进行分组,并返回每个组的聚合数据。
group by c.cno,c.cname;
具体来说,如果表c
包含学生的课程信息,每行代表一门课程,那么该查询将按照课程编号(cno
)和课程名称(cname
)对课程进行分组,并计算每个组中的行数、平均值、最大值等。
总结
参考代码:
insert into sc values ('1002','160006',76);
select c.cno,cname,count(*) from sc grade right join course c on c.cno=grade.cno
group by c.cno,c.cname;
参考结果: