由于篇幅的设置,文章中介绍了代码作用和书写规范,真正的案例操作我上传到了资源,建议大家自己去软件上运行一下MySql 基础练习题
关于MySql基础学习的链接,如下:
- 数据分析之MySql篇{数据库基础概念}
- 数据分析之MySql篇{数据定义DDL与数据操作DML}
- 数据分析之MySql篇{常用函数}
- 数据分析之MySql篇{练习题}
- 数据分析之MySql篇{电商数据处理案例}
SQL语句书写
SQL语句书写顺序
子句顺序 | 说明 | 是否必须使用 |
---|---|---|
SELECT | 要返回的列或表达式 | 是 |
FROM | 从中检索数据的表或视图 | 仅从中检索数据时使用 |
WHERE | 行级过滤 | 仅对记录进行筛选时使用 |
GROUP BY | 分组字段 | 仅在分组聚合运算时使用 |
HAVING | 组级过滤 | 仅对分组进行筛选时使用 |
ORDER BY | 输出排序 | 仅对查询结果进行排序时使用 |
LIMIT | 限制输出 | 仅对查询结果限制输出时使用 |
select 语句执行顺序
单表查询
- 全表查询:
select * from 表名;
- 查询指定列:
select 字段1[,字段2,…] from 表名;
这样查找出来并不是一个表,更不是一个视图,而是一个返回结果的数据集,且不占任何内存。
- 别名的设置:select 字段名 as 列别名 from 原表名 [as ]表别名;
select *,sal+1000 from emp; # 查询当中添加了新的字段,注意:原数据表中还是8个字段
select *,sal+1000 as 调薪 from emp;
- 查询不重复的记录:
select distinct 字段名 from 表名;
也可以进行多个字段的去重。
select distinct deptno from emp; select distinct deptno,job from emp;
- 条件查询:
select 字段1[,字段2,…] from 表名 where 查询条件;
查询条件一般来说使用运算符来表示:
算术运算符
算术运算符 | 作用 |
---|---|
+ | 加 |
— | 减 |
* | 乘 |
/ | 除 |
逻辑运算符
逻辑运算符 | 作用 |
---|---|
and | 且 |
or | 或 |
not | 非 |
比较运算符
比较运算符 | 作用 |
---|---|
= | 等于 |
>/>= | 大于/大于等于 |
</<= | 小于/小于等于 |
!=或者<> | 不等于 |
between…and… | 值范围 |
运算符优先级
优先级 | 运算符 |
---|---|
1 | () |
2 | 算术运算符 |
3 | 比较运算符 |
4 | 逻辑运算符 |
- 空值查询:
select 字段1[,字段2,…] from 表名 where 空值字段 is[ not] null;
空值与任何值进行运算,最后结果都为空
- 模糊查询:
select 字段1[,字段2,…] from 表名 where 字符串字段[ not] like 条件
通配符:
百分号(%)通配符:匹配多个字符
下划线(_)通配符:匹配一个字
模糊查询只能用于字符串类型的字段
- 查询结果排序:
select 字段1[,字段2,…] from 表名 order by 字段1[ 排序方向,字段2 排序方向,…];
多字段排序时,先按第一个字段排序,第一个字段值相同时再按第二个字段排序。指定排序方向:asc升序,desc降序(没有指定排序方向时,默认是asc升序)
- 限制查询结果数量:
select 字段1[,字段2,…] from 表名 limit [偏移量,] 行数;
limit接受一个或两个数字参数,参数必须是一个整数常量 ,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目
如果只给定一个参数,表示返回最大的记录行数目 初始记录行的偏移量是0(而不是1)
分组查询
聚合函数
聚集函数 | 说明 |
---|---|
avg() | 列的平均值 |
count() | 列的行数 |
max() | 列中最大值 |
min() | 列中最小值 |
sum() | 列中值的和 |
select count(*) 员工人数,max(sal) 最高工资,min(sal)最低工资,avg(sal)平均工资,sum(sal)工资综合
from emp;
所有的聚合函数,都会忽略空值
- 分组查询:
select 字段1[,字段2,…] from 表名[ where 查询条件] group by 分组字段1[,分组字段2,…];
将查询结果按照一个或多个字段进行分组,字段值相同的为一组,对每个组进行聚合计算
- 分组后筛选:
select 字段1[,字段2,…] from 表名[ where 查询条件][ group by 分组字段1[,分组字段2,…]] having 筛选条件;
where与having的区别:
where子句作用于表,having子句作用于组。
where条件查询的作用域是针对数据表进行筛选,而having条件查询则是对分组结果进行过滤。
where在分组和聚合计算之前筛选行,而having在分组和聚合之后筛选分组的行,因此where子句不能包含聚合函数。
多表查询
通过不同表中具有相同意义的关键字段,将多个表进行连接,查询不同表中的字段信息。
连接方式
- 内连接和外连接
外连接又分为左外连接和右外连接
多表连接的结果通过三个属性决定
- 方向性:在外连接中写在前边的表为左表、写在后边的表为右表
- 主附关系:主表要出所有的数据范围,附表与主表无匹配项时标记为null,内连接时无主附表之分
- 对应关系:关键字段中有重复值的表为多表,没有重复值的表为一表
一对一关系
一对多关系
多对多关系
为什么要拆分表呢
节省存储空间,避免数据冗余
比如说,当前我们有一个大表,存储着每一个学生姓名,课程id,以及学生对课程的考试成绩。
不难发现,这个表中数据显示的有点乱套了。又感觉有一些数据其实没必要重复多次,但是没有它还不行。那么我们把这个表拆成一对多的关系后呢?
拆分成了一张学生表,一张成绩表,一张课程表,学生表对成绩表是一对多的关系,课程表对成绩表也是一对多的关系,这样我们在观察这个数据的时候,是不是就感觉到清晰了很多呢。
内连接
按照连接条件合并两个表,返回满足条件的行。select 字段1[,…] from 表1[ inner] join 表2 on 表1.key=表2.key;
比如说:当前我们有t1和t2两个表,进行内连接
select *
from t1 inner join t2
on t1.key1 = t2.key2;
左连接
结果中除了包括满足连接条件的行外,还包括左表的所有行。
sselect 字段1[,…] from 表1 left join 表2 on 表1.key=表2.key;
如图A为主表,比如说:当前我们有t1和t2两个表,进行左连接
select *
from t1 left join t2
on t1.key1 = t2.key2;
右连接
结果中除了包括满足连接条件的行外,还包括右表的所有行。
select 字段1[,…] from 表1 right join 表2 on 表1.key=表2.key;
如图B为主表,比如说,当前我们有t1和t2两个表,进行右连接
select *
from t2 right join t1
on t1.key1 = t2.key2;
联合查询
把多条select语句的查询结果合并为一个结果集。被合并的结果集的列数、顺序和数据类型必须完全一致
- union去重:
select 字段1[,字段2,…] from 表名 union select 字段1[,字段2,…] from 表名
# 以t1 和t2 为例子
select *
from t1
union
select *
from t2;
- union all不去重:
select 字段1[,字段2,…] from 表名 union all select 字段1[,字段2,…] from 表名;
select *
from t1
union all
select *
from t2;
子查询
一个select语句中包含另一个或多个完整的select语句。
子查询出现的位置
- 出现在
where
子句中:将子查询返回的结果作为主查询的条件
注意:where子句不允许出现聚合函数,如果要用到聚合函数,就要把聚合函数的结果定义别名。
- 出现在
from
子句中:将子查询返回的结果作为主查询的一个表
子查询分类
- 标量子查询:返回的结果是一个数据(单行单列)
select 字段1[,字段2,…] from 表名 where 字段 = 返回结果为单行单列的select子句;
- 行子查询:返回的结果是一行(单行多列)
select 字段1[,字段2,…] from 表名 where (字段1,字段2,.....) = 返回结果为单行多列的select子句;
- 列子查询:返回的结果是一列(多行单列)
列子查询用到的操作符
语义 | 操作符 | 使用格式 |
---|---|---|
在(不在)其中 | [NOT] IN | <字段>IN数据表(子查询) |
任何一个 | ANY | <字段><比较>ANY数据表(子查询) |
全部(每个) | ALL | <字段><比较>ALL数据表(子查询) |
select 字段1[,字段2,…] from 表名 where (字段1,字段2,.....) 操作符 (返回结果为单行多列的select子句);
- 表子查询:返回的结果是一张临时表(多行多列),也可以理解为虚拟结果集。
作为子查询的表,必须要设置别名
select empno,ename,sal,emp.deptno
from emp left join (select deptno,max(sal) as 最高工资 from emp group by deptno) as t on emp.deptno = t.deptno
where sal=最高工资;