数据分析—mysql多表查询

数据分析—mysql多表查询

1.表的加法:union

1.1 表的加法:union, unionl连接的两个表的结构需要一样。

1.2 union 重复的数据行去重;union all 保留重复的数据行;

1.3实例:

-- 1.3.1 表的加法 union ,union 重复的数据行去重.

 select 课程号,课程名称 from course
 union 
 select 课程号,课程名称 from course1;

-- 1.3.2 表的加法 union ,union all 保留重复的数据行;

 select 课程号,课程名称 from course
 union  all
 select 课程号,课程名称 from course1

2.表的联结:

表和表之间是通过列产生关系的。


2.1 表的联结:交叉联结

2.1.1交叉联结概述

交叉连接也叫笛卡尔积,cross join,交叉连接是表中的每一行,都与另一个表中的每一行合并在一起。

如图:


表一有三行数据,用1,2,3分别表示表中的三行数据,

表二有两行数据,用a,b分别表示表中的两行数据,

表一和表二进行交叉联结的过程,是这样的,

表一的第一行数据分别与表二中的两行合并在一起,这样就产生了两行数据;

表一的第二行数据分别与表二中的两行合并在一起,这样又产生了两行数据;

表一的第三行数据分别与表二中的两行合并在一起,这样又产生了两行数据;

交叉连接结果的行数,是两张表中行数的成绩,表一有三行数据,表二有两行,所以他有3*2= 6行数据。


交叉连接在生活的体现:扑克牌

扑克牌有4种花色,有13张牌,4*13=52张牌,加上大小王,合计54张牌。


交叉联结的业务应用

交叉连接在实际业务中应用比较少,其结果行数太多,没有什么价值,那为什么使用呢,是因为交叉连接是所有连接的基础,其他的连接都是在此基础上增加了过滤条件。


2.2表的联结:内联结

定义:查找出同时存在于两张表中的数据,inner join。

练习:查询学生的学号,姓名和课程号

第一步:

1.两个表通过学号进行内连接,将两个表中都有的学号所在的行都取出来。

2.学生表里取出的是学号0001这一行,成绩表中0001有两行取出两行数据,

第二步:将两个表里取出的数据通过交叉联结方式合并,

将成绩表001这一行,分别与成绩表中两个合并,最终产生两行数据,合并后的表有了两个表里的全部信息。

CREATE TABLE if not EXISTS score1(
`学号` VARCHAR(50),
`课程号` VARCHAR(50),
`成绩` int,
PRIMARY KEY(`学号`,`课程号`)
INSERT into score1 VALUES
('0001','0001',80),
('0001','0002',90),
('0005','0003',60)
CREATE TABLE IF NOT EXISTS student1(
`学号` int PRIMARY KEY,
`姓名` VARCHAR(50),
`出生日期` VARCHAR(50),
`性别` VARCHAR(50)
insert into student1 VALUES
('0001','猴子','1989-01-01','男'),
('0002','猴子','1990-12-21','女')
# 语句:
select a.学号,a.姓名,b.课程号
from student1 as a 
inner join score1 as b
on a.学号 = b.学号;

2.3表的联结:左联结

定义:左联结将左侧表中的数据全部取出来

分析:

第一步:两个表通过学号产生了匹配关系,左侧的表做为主表,全部被读取出来,右边的表中只选出和左边表相同学号的行,也就是学号0001所在的两行数据,

第二步:将两个表取出的数据通过交叉联结方式做合并,因为学号0002在右边的表里没有对应的行,所以这一行对应的列的值是空值。

如图:

语句:

select a.学号,a.姓名,b.课程号
from student1 as a 
left join score1 as b
on a.学号 = b.学号;

2.3.1 去除重合数据的左联结。

如图:

语句:

select a.学号,a.姓名,b.课程号
from student1 as a 
left join score1 as b
on a.学号 = b.学号
where b.课程号 is null

2.4表的联结:右联结

定义:右联结将右侧表中的数据全部取出来

运行:

第一步:两个表通过学号产生了匹配关系,右侧的表做为主表,全部被读取出来,左边的表中只选出和右边表相同学号的行,也就是学号0001所在的一行数据。

第二步:将两个表取出的数据通过交叉联结方式做合并,因为学号0005在右边的表里没有对应的行,所以这一行对应的列的值是空值。

如图:

语法:

select a.学号,a.姓名,b.课程号
from student1 as a 
right join score1 as b
on a.学号 = b.学号;

2.4.1 去除重合数据的右联结。

如图:

select a.学号,a.姓名,b.课程号
from student1 as a 
right join score1 as b
on a.学号 = b.学号
where a.学号 is null


2.5 表的联结:全联结

mysql 不支持全联结,理解概念即可。

定义:全联结查询结果返回左表和右表中的所有行,如果某一行和另一个表中行有匹配的时候了,两个行进行合并,如果某一行和另一个表中没有匹配的行的时候,另一个表的值对应的地方用空值填充。


3.sql解决业务的三个步骤:

练习1:查询所有学生的学号,选课数,总成绩。

select st.学号,count(s.课程号) 选课数,sum(s.成绩) 总成绩
from student st 
left join score s 
on s.学号 = st.学号
GROUP BY st.学号

练习2:查询平均成绩大于85分的所有学生的学号和平均成绩

第一步:翻译

1.查询出所有学生的学号和平均成绩。

  • 学号(student 表)
  • 平均成绩(每个学生的平均成绩:在score表中,按照学号分组;平均成绩:avg(成绩))

2.平均成绩>85

第二步:分析

第三步:sql语句

select st.学号,avg(s.成绩) 平均成绩
from student st
left join score s
on st.学号 = s.学号
GROUP BY st.学号
having avg(s.成绩) >85;

第四步:结果

-- 练习3:查询学生的选课情况:学号,姓名,课程号,课程名称。

第一步:翻译

1.查询出所有学生的学号,姓名,课程号,课程名称

  • 学号、姓名(student )
  • 课程号、课程名称(course)

2.student做主表进行左联结(left join)

3.通过score表对student表和course表进行连接。

  • student与score(学号)
  • course 与score(课程号)

第二步:分析

第三步:sql语句

select st.`学号`,st.`姓名`,c.`课程号`,c.`课程名称`
from student st 
left join score s on st.学号 = s.学号
left join course c on s.`课程号` = c.`课程号`

第四步:查询结果展示

4. case表达式

4.1 case概述

定义:使用case表达式可以帮助我们解决复杂的查询问题,case表达式的作用就相当于进行一个条件判断的函数,用来判断每一行是不是满足某个条件。

语法:

CASE WHEN <判断表达式> THEN <表达式1>
     WHEN <判断表达式> THEN <表达式2>
     WHEN <判断表达式> THEN <表达式3>
     ELSE <表达式>
END

练习1:查询学生成绩是及格还是不及格(>=80分及格);

select 学号,课程号,成绩,
(case when 成绩>=80 then '及格'
      when 成绩<80 then '不及格'
			else null 
end) as 是否及格
from score

练习2:查询每门课程的及格人数,和不及格人数。

select 课程号,
sum(case when 成绩>=80 then 1 else 0 end) 及格人数,
sum(case when 成绩<80 then 1 else 0 end) 不及格人数
from score
GROUP BY 课程号

4.2 case表达式注意事项:

1.else 可以省略不写,默认为空值,但是不建议省略。

2.end 不可以省略。

3.case表达式可以写在 sql表达式的任意子句里面

4.3 应用场景:

当有多种情况需要条件判断的时候可以使用case表达式。


练习1:使用分段[100-85],(85-71],[70-60],(<60]来统计各科成绩,分别统计各分数段人数,课程号和课程名称。

第一步:翻译

1.对课程号和课程名称分组,group by 课程号,课程名称。

2.根据要求对成绩进行分段。

[100-85] 成绩<=100 and 成绩>=85 同 between 85 and 100

[85-71] 成绩< 85 and 成绩>=70

[70-60] 成绩< 70 and 成绩>=60

[[<60] 成绩<60

3.对分组和分段数据进行笛卡尔积连接。

第二步:分析

第三步:sql语句

select c.课程号,c.课程名称,
sum(case when 成绩<=100 and 成绩>=85 then 1 else 0 end) '[100-85]',
sum(case when 成绩< 85  and 成绩>=70 then 1 else 0 end) '[85-71]',
sum(case when 成绩< 70 and 成绩>=60 then 1 else 0 end) '[70-60]',
sum(case when 成绩<60 then 1 else 0 end) '[<60-5]'
from course c 
join  score s on c.课程号 = s.课程号
GROUP BY c.课程号,c.课程名称


sqlzoo练习:The JOIN operation/zh。 The JOIN operation/zh

1.SELECT matchid, player  FROM goal 
  WHERE teamid = 'GER'
2.SELECT id,stadium,team1,team2
  FROM game where id = '1012'
3.SELECT go.player,go.teamid,ga.stadium,ga.mdate
 FROM game  ga
JOIN goal  go
ON (id=matchid)
where go.teamid = 'GER'
4.select team1,team2 ,player
from game 
join goal 
on (id=matchid)
where player LIKE 'Mario%'
5.SELECT player, teamid,coach, gtime
FROM goal 
join eteam 
on teamid=id
WHERE gtime<=10
6.select g.mdate,e.teamname
from game g
join eteam e