多表查询过滤重复数据_数据分析之数据库的多表查询

b7bcade6913b1ebe4349cc9083747486.png

表的加法——UNION

  1. 什么是表的加法?

将两个表的所有数据合并在一起,重复项仅保留一项

2. 文氏图

3d10efbc7b63cb5b2158d6221c17d6e3.png

3. 示例

SELECT `课程号`,`课程名称` 
FROM course
UNION
SELECT `课程号`,`课程名称` 
FROM course1;

【运行结果】

3c081305c344bcc21dff0cf8dca38802.png
UNION

4. 使用UNION对表进行合并,但需要保留重复行时,使用UNION ALL

示例:

SELECT `课程号`,`课程名称` 
FROM course
UNION ALL
SELECT `课程号`,`课程名称` 
FROM course1;

【运行结果】

d50a4cec6fc1f2a5e2ce854d2800dd3c.png
UNION ALL

表的联结

要对个表进行联结,需要先理清各表之前的关系,以下为数据库中四个表的连接关系图

facc466bb9ecacd65389496728119d99.png
联结关系图
  1. 交叉联结CORSS JOIN(又称:笛卡尔积)

1)定义:

将表中的每一行都和另一个表中的每一行联结在一起

2)交叉联结示例:

e8cd3a95d83466fe23bd9abff603b3ea.png
交叉联结定义

3)使用场景:

交叉联结的使用场景少,因为需要处理的数据量大会占用比较大的内存,但是交叉联结是其他联结的基础,其他联结是在交叉联结上过滤所得到的效果。

2. 内联结INNER JOIN

1)文氏图

8afcc638a7ecc5b4bd58164d3ed7437d.png

2) 运行逻辑:找出对应条件中的字段相同的数据,将两个表中该字段对应的每行数据提取出来,然后将两个表进行交叉联结。

61ff67fa72978a22718789cffc0c678d.png

3)示例:

SELECT a.`学号`,a.`姓名`,b.`课程号`
FROM student AS a INNER JOIN score AS b
ON a.`学号`=b.`学号`;

等价于:

SELECT a.`学号`,a.`姓名`,b.`课程号`
FROM student AS a, score AS b
where a.`学号`=b.`学号`;

【运行结果】

b9a5eb1aed2e7465694d452aa4ac711c.png

3. 左联结 LEFT JOIN

1)文氏图

0209b3a4e5370c16c6d7aad940b8b495.png

2)运行逻辑:将左侧的表作为主表,将所有数据取出来,右边的表取出符合条件的行,并将取出的数据进行交叉联结,右表取出来的数据,如果左表没有对应的行,则设为空值

84667d66d22f548c56f56b1fefebde7f.png

3)示例:

SELECT a.`学号`,a.`姓名`,b.`课程号`
FROM student AS a LEFT JOIN score AS b
ON a.`学号`=b.`学号`;

【运行结果】

caa8984b039d4d14c746475e9fe50092.png

4)左联结的基础上去掉公共部分

a.文氏图

38dce9cb30a78090b33d36f76f87110f.png

b.示例:

SELECT a.`学号`,a.`姓名`,b.`课程号`
FROM student AS a LEFT JOIN score AS b
ON a.`学号`=b.`学号`
WHERE b.`学号`is NULL;

【运行结果】

0345bf1e7490ad73800fb56c720c83dc.png

4. 右联结RIGHT JOIN

1)文氏图

c8e9795546edc1847393850923b7a1b4.png

2)运行逻辑

将右侧的表作为主表,将所有数据取出来,左边的表取出符合条件的行,并将取出的数据进行交叉联结,左表取出来的数据,如果右表没有对应的行,则设为空值。

1ffd29c535155ce6d3d7b67bd77f180a.png

3)示例:

SELECT a.`学号`,a.`姓名`,b.`课程号`
FROM student AS a RIGHT JOIN score AS b
ON a.`学号`=b.`学号`;

【运行结果】

9ea0d2d13fadbc2a5bb0768b99458f85.png

4)右联结的基础上去掉公共部分

a.文氏图

97dd3837abf77fc5675352302eff93d1.png

b.示例:

SELECT a.`学号`,a.`姓名`,b.`课程号`
FROM student AS a RIGHT JOIN score AS b
ON a.`学号`=b.`学号`
WHERE a.`学号` is NULL;

【运行结果】

57f994d61b4f87ca9396724e437e4be9.png

5. 全联结 FULL JOIN

1)文氏图

ba9e73a8ca5d3de1c9a9955f91ce8eb0.png

2)运行逻辑

返回左表和右表的所有行,无对应值时用空值填充

3)注意

mysql中不支持全联结 FULL JOIN

5. 联结总结图

005cda512f715eb916ed473586fe0c46.png

6. 加入联结后的运行顺序

0b7b924ea243548e2042ba42b978da09.png

7. 练习

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

【解题】

学号、姓名-学生表中

选课数-课程表中按照学号分类,并对课程号进行计数

总成绩-成绩表中按照学号分类,对成绩求和

【分析】

SELECT 查询结果[学号、姓名、选课数、总成绩]

FROM 从哪张表中查数据[[学号、姓名-学生表,选课数、总成绩-成绩表,左联结]

WHERE [没有]

GROUP BY [学号]

HAVING [没有]

ORDER BY [没有]

LIMIT [没有]

【答案】

SELECT a.`学号`,a.`姓名`,COUNT(b.`课程号`) AS 课程数,SUM(b.`成绩`) AS 总成绩
FROM student AS a LEFT JOIN score AS b
ON a.`学号`=b.`学号`
GROUP BY a.`学号`;

【运行结果】

856176e59819e49520bf8a66ff4a457e.png

2)查询平均成绩大于85的所有学生的学号、姓名和平均成绩

【解题】

学号、姓名-学生表中

平均成绩数-课程表中按照学号分类,求学生的平均成绩

【分析】

SELECT 查询结果[学号、姓名、平均成绩]

FROM 从哪张表中查数据[[学号、姓名-学生表,平均成绩-成绩表,左联结]

WHERE [没有]

GROUP BY [学号]

HAVING [成绩>15]

ORDER BY [没有]

LIMIT [没有]

【答题】

SELECT a.`学号`,a.`姓名`,AVG(b.`成绩`) AS 平均成绩
FROM student AS a LEFT JOIN score AS b
ON a.`学号`=b.`学号`
GROUP BY a.`学号`
HAVING AVG(b.`成绩`)>85;

【运行结果】

f3dab749e37ba166cade91518b03aa2f.png

3)查询学生的选课情况:学号,姓名,课程号,课程名称

【解题】

学号、姓名-学生表

课程号-成绩表

课程名称-课程表

学生表与成绩表用学号进行左联结,获得学号、姓名、课程号

再用上面的结果与课程表进行左联结,拿到课程名称

【分析】

SELECT 查询结果[学号,姓名,课程号,课程名称]

FROM 从哪张表中查数据[(学号、姓名-学生表,课程号-成绩表)内联结,课程名称-课程表,内联结]

WHERE [没有]

GROUP BY [学号]

HAVING [没有]

ORDER BY [没有]

LIMIT [没有]

【答案】

SELECT a.`学号`,a.`姓名`,b.`课程号`,c.`课程名称`
FROM student AS a INNER JOIN score AS b ON a.`学号`=b.`学号` 
INNER JOIN course AS c ON b.`课程号`=c.`课程号`;

【运行结果】

5d20e2863d97168fa0c60444c422b496.png

CASE表达式

  1. 定义

条件判断函数,判断每一行是否满足格式

case when <判断表达式> when <表达式>

<判断表达式> when <表达式>
<判断表达式> when <表达式>

...

else <表达式>

end

2. 运行逻辑

将表中的每一行的数据拿出来,从上往下与判断表达式进行比较,符合条件时执行对应的表达式,直接完成后执行end结束,再取出表中的下一行数据,一直到数据读取完毕。

3. 示例:查询出每门课程的及格人数和不及格人数

SELECT `课程号`,
SUM(CASE WHEN `成绩` >=60 THEN 1
	ELSE 0
	END) AS 及格人数,
SUM(CASE WHEN `成绩` <60 THEN 1
	ELSE 0
	END) AS 不及格人数
FROM score
GROUP BY `课程号`

【运行逻辑】

582d49bb58a93509033761a82041d304.png

【运行结果】

e70d7778fe01b3c5939b569108f98dc3.png

4. 注意事项

1)else可以省略,省略时默认为空值

2)end可以省略

3)case语句可以放在任意子句中

5. 练习

1)使用分段[100-85],[85-70],[70-60],[<60]

来统计各科成绩,分别统计:

各分数段人数,课程号和课程名称

【分析】

各分数段人数,课程号在成绩表,课程名称在课程表

先将左联结课程表,找出课程号对应的课程名称

再按照课程号、课程名称分组,并将成绩类成不同分数段,使用case统计人数

【答案】

SELECT a.`课程号`,b.`课程名称`,
SUM(CASE WHEN a.`成绩` BETWEEN 85 AND 100 THEN 1
	ELSE 0
END) AS '[100-85]',
SUM(CASE WHEN a.`成绩` >=70 THEN 1
	ELSE 0
END) AS '[85-70]',
SUM(CASE WHEN a.`成绩` >=60 THEN 1
	ELSE 0
END) AS '[70-60]',
SUM(CASE WHEN a.`成绩` <60 THEN 1
	ELSE 0
END) AS '[<60]'
FROM score AS a RIGHT JOIN course AS b
ON a.`课程号`=b.`课程号`
GROUP BY a.`课程号`,b.`课程名称`

【运行结果】

bec0c72d1ba1d64cf5b0f7dc7adf9e31.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值