sql减法语句_SQL入门之多表查询

表的运算

1、表的加法(UNION),表的减法(EXCEPT),表的交集(INTERSECT);

2、表运算的注意事项:作为运算对象的表的列数必须相同;类型必须相同;可以使用任何select子句,但是order by只能在最后一次使用;默认结果不包含重复行,但是如果想保留重复行需要在后面加入ALL关键字。

联结

简单来说,联结就是将其他表中的列添加过来。一般我们期望得到的数据都是分散在多张表的,使用联结就可以从多张表中获取数据了。

下面使用teacher表和course表来说明以下几种联结方式:

1、交叉联结,又叫笛卡尔积,意义不大,使用场景极为少见。

2、Left join(左联结)A left join B表示从A表中取出完整的表记录,然后再匹配B表,在B表找不到匹配项的记录,对应B表的字段会显示NULL;下面对course表和teacher表左联结:

SELECT
	CS.教师号,
	CS.课程号,
	CS.课程名称,
	TC.教师姓名
FROM
	course AS CS
LEFT JOIN teacher AS TC ON CS.教师号 = TC.教师号;

0f2892bb37bb14803c404bb00a3ac314.png

3、Right join(右联结)A right join B表示从B表中取出完整的表记录,然后再匹配A表,在A表找不到匹配项的记录,对应A表的字段会显示NULL;下面对course表和teacher表右联结:

SELECT
	CS.教师号,
	CS.课程号,
	CS.课程名称,
	TC.教师姓名
FROM
	course AS CS
RIGHT JOIN teacher AS TC ON CS.教师号 = TC.教师号;

ba2fc3cb25c6759bef5ebd48a5faa180.png

4、Inner join(内联结)A inner join B表示显示A表和B表共有的字段对应的记录。下面对course表和teacher表内联结:

SELECT
	CS.教师号,
	CS.课程号,
	CS.课程名称,
	TC.教师姓名
FROM
	course AS CS
INNER JOIN teacher AS TC ON CS.教师号 = TC.教师号;

b5299536fa7af0a7d444400f9ebe04e7.png

5、Full join:MySQL不支持全联结,需要使用左右联结UNION构造。下面对course表和teacher表做全联结:

(SELECT
	CS.教师号,
	CS.课程号,
	CS.课程名称,
	TC.教师姓名
FROM
	course AS CS
LEFT JOIN teacher AS TC ON CS.教师号 = TC.教师号)
UNION

(SELECT
	TC.教师号,
	CS.课程号,
	CS.课程名称,
	TC.教师姓名
FROM
	course AS CS
RIGHT JOIN teacher AS TC ON CS.教师号 = TC.教师号)

4553425db56b062d9071d412bd1117cf.png

6、一张图读懂sql联结

00b8a57f7c747e184c64224544927714.png

练习题

第一部分:sqlzoo练习题:https://sqlzoo.net/wiki/The_JOIN_operation/zh

练习整体比较简单,仅对踩过坑的几点在此说明:

第11题For every match involving 'POL', show the matchid, date and the number of goals scored.要求既要显示matchid又要显示date,我开始只是使用了matchid做group by的条件,这样会报错:‘a.mdate' isn't in GROUP BY,所以这个时候需要将a.mdate也要写入group by才能pass。重新复习下group by存在的时候select子句中只能使用group by中的列名称以及聚合函数。

SELECT
	a.id,
	a.mdate,
	count(b.player)
FROM
	game AS a
INNER JOIN goal AS b ON a.id = b.matchid
WHERE
	(team1 = 'POL' OR team2 = 'POL')
GROUP BY
	a.id,
	a.mdate

第13题考察的是case语句,后续使用的多了,会单独写总结:

SELECT
	a.mdate,
	a.team1,
	sum(
		CASE
		WHEN b.teamid = a.team1 THEN
			1
		ELSE
			0
		END
	) AS score1,
	a.team2,
	sum(
		CASE
		WHEN b.teamid = a.team2 THEN
			1
		ELSE
			0
		END
	) AS score2
FROM
	game AS a
LEFT JOIN goal AS b ON a.id = b.matchid
GROUP BY
	a.id,
	a.mdate,
	a.team1,
	a.team2;

第二部分:针对student表,teacher表,score表和course表,做如下练习题:

  • 查询所有学生的学号、姓名、选课数、总成绩
  • 查询平均成绩大于85的所有学生的学号、姓名和平均成绩
  • 查询学生的选课情况:学号,姓名,课程号,课程名称
  • 查询出每门课程的及格人数和不及格
  • /*使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分数段人数,课程号和课程名称*/
-- 查询所有学生的学号、姓名、选课数、总成绩,保存为视图,方便后续使用
CREATE VIEW score_stu_view (
	出生日期,
	姓名,
	学号,
	性别,
	成绩,
	课程号
) AS SELECT
	stu.出生日期,
	stu.姓名,
	stu.学号,
	stu.性别,
	sc.成绩,
	sc.课程号
FROM
	student AS stu
INNER JOIN score AS sc ON stu.学号 = sc.学号;
SELECT
	学号,
	姓名,
	COUNT(课程号) AS 选课数,
	SUM(成绩) AS 总成绩
FROM
	score_stu_view
GROUP BY
	学号;
-- 查询平均成绩大于85的所有学生的学号、姓名和平均成绩
SELECT
	学号,
	姓名,
	AVG(成绩) AS 平均成绩
FROM
	score_stu_view
GROUP BY
	学号
HAVING
	平均成绩 > 85;
-- 查询学生的选课情况:学号,姓名,课程号,课程名称
CREATE VIEW course_score_view(姓名,学号,成绩,课程号,课程名称) AS SELECT
	stu.姓名,
	stu.学号,
	sc.成绩,
	sc.课程号,cs.课程名称
FROM
	student AS stu
INNER JOIN score AS sc ON stu.学号 =sc.学号
INNER JOIN course AS cs ON sc.课程号 =cs.课程号;
-- 查询出每门课程的及格人数和不及格
SELECT
	课程号,
	sum(
		CASE
		WHEN 成绩 >= 60 THEN
			1
		ELSE
			0
		END
	) AS 及格人数,
	sum(CASE WHEN 成绩 < 60 THEN 1 ELSE 0 END) AS 不及格人数
FROM
	course_score_view
GROUP BY
	课程号;
/*使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分数段人数,
课程号和课程名称*/
SELECT
	课程号,
	课程名称,
	sum(
		CASE
		WHEN 成绩 > 85
		AND 成绩 <= 100 THEN
			1
		ELSE
			0
		END
	) AS 一等,
	sum(
		CASE
		WHEN 成绩 > 70
		AND 成绩 <= 85 THEN
			1
		ELSE
			0
		END
	) AS 二等,
	sum(
		CASE
		WHEN 成绩 >= 60
		AND 成绩 <= 70 THEN
			1
		ELSE
			0
		END
	) AS 三等,
	sum(CASE WHEN 成绩 < 60 THEN 1 ELSE 0 END) AS 不及格
FROM
	course_score_view
GROUP BY
	课程号;

备注:本文示例代码使用的表

108240cfd9043e35f54753dad5fdcef3.png
course表

60dc1750eff2197127281689812ec69c.png
teacher表

338cb2af7bdbbf8072ed3b6ddff7b9d1.png
score表

29b6685b1062b522f0a73be31af8afd8.png
student表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值