本文主要介绍了如果根据表之间的关系设计表,以及mysql的聚合/分组/联合查询.
一.表的设计
实体和关系的四种关系
1.一对一
一个账号只能对应一个学生;
一个学生只能有一个账号;
比如:账号表和学生是一对一的关系
* 可以在账号表中引入学生id
* 也可以在学生表中引入账号id
2.一对多
一个学生只能在一个班级;
一个班级可以包含多个学生;
3.多对多
一个同学可以选择多门课程来学习;
一个课程可以被多个同学来选择;
往往表示多对关系,需要引入一个关联表
4.没关系
如果两个实体没有关系,那么两张表就完全独立,互不影响
上述这几种数据库表的设计方式都是最常见的.
二.查询高阶
1.insert+select
将select查询结果插入到另一个表中
要求查询的列的个数/类型和被插入的表一致
2.聚合查询
行和行之间的运算
>聚合函数
count( distinct 表达式 ) | 返回查询到的数据的数量 |
sum() | 返回查询到的数据的总和,非数字无意义 |
avg() | 返回平均值,非数字无意义 |
max() | 返回最大值,非数字无意义 |
min() | 返回最小值,非数字无意义 |
- count
count(*) 如果是一行全空记录,仍然会被算在被
count(某列) 空值不会算在内
注意:count和( )必须要仅仅黏在一起,否在报错
- sum
求和,把这一列的若干行,进行累加
只能针对数字进行相加
对字符串进行求和 , 没有效果,并且会产生警告
3.分组查询
上述的聚合函数是把表中的所有行都放在一起
有的时候,希望把数据进行分成多组来进行计算
Group by子句
指定一个列,按照这一列进行分组 ; 这一类中,数值相同的行,会被分到一组
每个分组都都可以使用上述的聚合函数进行计算
计算1班和2班的语文/数学平均分(以班级分组)
select中指定的列必须是必须是group by 指定的列 ,
如果select中想用其他的列,其他列必须放到聚合函数中, 否则此时查询的结果无意义.
比如 name只是分组的第一个代表,它实际上并没有什么意义
分组查询,也可以搭配条件来使用
1.分组之前的条件 | where |
2.分组之后的条件 | having |
1.分组之前的条件
比如,在分组之前有一个排除张三的条件
2.分组之后的条件
分组之后的条件也要搭配聚合函数来使用 !!
比如求每个班级的语文平均分>70的
3.同时包含分组前的条件和分组后的条件
求每个班级除去张三之后的平均分>70的班级
在实际开发中,可能会涉及到一些比较复杂的sql, 但是sql写复杂了其实是不好的
可读性不好和执行效率都可能比较差 , 不建议写太复杂的sql !
4.联合查询
也叫多表查询 , 最复杂的写法
3.1 内连接
select 字段 from 表1 , 表2 where 连接条件 and 其他条件
或者
select 列名 from 表1 inner join 表2 on 连接条件 and 其他条件
(用inner join/join来连接表 , 用on来表示连接条件 )
eg.
笛卡尔积(数学上的运算)
就是把两个表的记录,按照排列组合的方式,构造成一个更大的表
笛卡尔积的列数: 两个表的列数之和
笛卡尔积的行数: 两个表的行数之积
针对任意两张表都可以计算笛卡尔积
笛卡尔积是一个非常低效的操作,尤其是表的本身的记录比较多的情况
笛卡尔积中有些数据是符合实际情况的,有些事不符合实际情况的
所以需要用连接条件来筛选符合实际情况的数据
示例:
a.两个表进行笛卡尔积
将学生表和班级表进行笛卡尔积
b.指定连接条件
增加连接条件
如果是多表查询,条件中最好写作 表名.列名 的形式
笛卡尔积+必要的条件= >多表联合查询
- 查询lisi同学的所有成绩
- 求每个学生的总成绩
- 求每个学生选了几门课
- 查询所有同学的成绩,课程名字和分数(三张表进行笛卡尔积)
注意此处能够写出连接条件是因为这几个实体之间存在关联关系
3.2外连接
join on 还可以表示外连接
外连接 VS 内连接
1.
左侧表的每一条记录,都能在右侧找到对应;
右侧表的每一条记录,也能在左侧找到对应;
此时,这两个表,进行内连接和外连接的结果完全相同 ;
2.
此时这张表并不是相互一一对应的
内连接产生的结果,一定是两个表中都存在的数据 (公共的部分)
外连接在mysql里有两种情况 ,左外连接 / 右外连接 left join / right join
1.左外连接 . 就是以左侧的表为主.
左侧表的每个记录都会在最终结果里 ;
如果某条记录左侧有,而右侧没有,就把对应的列设为空值
2.右外连接,以右侧的表为主
还有一种outer join 全外连接,就是左外连接和右外连接求并集 (mysql不支持)
注意:
多表联合查询的使用,一定要克制 , 既会影响到运行效率,又会影响到开发效率 (可读性差) , 所以千万不要以写复杂sql为荣!
3.3 自连接
本质上是自己和自己做笛卡尔积,本质是把行之间的关系转换为 列之间的关系
SQL中编写条件,条件都是列和列之间进行比较 , 但是SQL无法进行行和行之间的比较, 但是 把行转换成列 就好办了
* 计算1号课程成绩小于2号课程成绩的同学
2.4子查询
日常开发中,使用子查询,更要克制!
* 查询和张三同学同班的同学
就相当于套娃 ,把两个sql 套在一起
不建议这么写 ,开发效率和可读效率都不高.
注意: in / exsits 也是可以使用的
2.5合并查询
union/union all 合并查询,把多个select查询到的结果集合合并成一个集合
合并的前提是两个查询的结果集,列是对应的
or也是把一些结果合并出来,只能局限在一个表里,
union可以针对任意连个表;
总结:
红框重点掌握,面试考察!