一、表的增删查改
1.1 插入数据
1.1.1insert
语法:
sql
INSERT [INTO] table_name
[(column [, column] ...)]
VALUES (value_list) [, (value_list)] ...
value_list: value, [, value] ...
使用示例:

1.单行数据+全列插入

2.单行数据+指定列插入

3.多行数据+全列插入

4.多行数据+指定列插入

在insert插入过程中可能会因为主键或者唯一键对应的值已经存在而导致插入失败

此时我们可以选择性地同步更新操作语句,语法如下:
sql
INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...
在更新数据时要保证不能和其他的主键或唯一键冲突!
1.1.2 replace
在发生主键或唯一键冲突时,除了使用上面的update,我们还可以直接使用replace来替换
语法:
sql
REPLACE [INTO] table_name
[(column [, column] ...)]
VALUES (value_list) [, (value_list)] ...
value_list: value, [, value] ...
replace在主键或唯一键没用冲突时会直接进行插入,当发生冲突时,则先对数据进行删除再进行插入操作。
使用示例:

1.2 查询数据
1.2.1 select
语法:
sql
SELECT
[DISTINCT] {* | {column [, column] ...}}
[FROM table_name]
[WHERE ...]
[ORDER BY column [ASC | DESC], ...]
LIMIT ...
使用示例:
1.全列查询
sql
select * from table_name

但是通常情况下不建议使用*来进行全列查询,原因是一个数据库中可能有几千万条数据,如果全部查询需要传输的数据量非常大,非常浪费资源;其次,全列查询可能会影响索引的使用。
2.指定列查询
sql
select xx from table_name

指定列查询时还可以同时指定多列进行查询,select会将查询的结果拼入表格中:

同时在查询时我们可以对数据进行求和,并且将求和的结果重命名后作为新的一列并入查询结果:

重命名可以带as也可以不带as
在使用select时添加distinct字段可以去除对选中的字段的查询结果中重复的数据。例如下图中在不带上distinct字段前的结果是这样的:

带上distinct字段之后结果如下图所示:

1.2.2 where条件
当我们需要对做结果进行筛选时就需要使用到where条件,下面是使用where条件进行条件筛选时较为常用的运算符。
1.比较运算符:
| 运算符 | 说明 |
|---|---|
>, >=, <, <= |
大于,大于等于,小于,小于等于 |
= |
等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> |
等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE (1) |
!=, <> |
不等于 |
BETWEEN a0 AND a1 |
范围匹配,a0, a1,如果 a0 <= value <= a1,返回 TRUE (1) |
IN (option, ...) |
如果是 option 中的任意一个,返回 TRUE (1) |
IS NULL |
是 NULL |
IS NOT NULL |
不是 NULL |
LIKE |
模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符 |
2.逻辑运算符:
| 运算符 | 说明 |
|---|---|
| AND | 多个条件必须都为 TRUE (1),结果才是 TRUE (1) |
| OR | 任意一个条件为 TRUE (1), 结果为 TRUE (1) |
| NOT | 条件为 TRUE (1),结果为 FALSE (0) |
MySQL中支持多条件组合查询,使用示例如下:


当我们统计表中的总分并查询其中总分小于200的同学的姓名和总分,根据前面的知识我们可能会写出这样的语句:

但是这样的语句是必然会报错的。原因是select是先执行from,再执行where按条件筛选,最后再执行加和并重命名,所以mysql不认识total,所以在where筛选时无法识别total,所以只能像下面这样写:

1.2.3 order by
使用order by可以对结果进行排序,order by默认升序排序:

需要注意的是,使用order by对数据进行排序时,首先需要有对应的数据。所以order by要先拿到数据之后才能对数据排序。因此该语句的执行顺序是在重命名语句的后面,所以在上面的例子中使用别名不会报错。
如果需要使用降序排序我们可以在后面加上desc:

1.2.4 limit
我们可以添加limit选项来筛选分页结果,进行简单的分页功能。其中,limit n表示从表的第0行开始连续读取n行数据;limit 2,4表示从指定位置开始连续读取多少条记录。


建议在对未知表进行查询时,加上一条limit 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
由于limit的本质功能时进行分页显示,所以只有数据准备好了,才能进行显示。故limit的执行顺序在order by之后。所以数据的查询操作的执行顺序如下:select1-from2-where3-order by4-limit5
1.3 修改数据
1.3.1 update
当我们需要修改表中的数据时,可以使用语句update
语法:
sql
UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
使用示例:

更新数据后的效果:

1.4 删除数据
1.4.1 delete
使用delete语句可以删除表中指定的数据
语法:
sql
UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
1.4.2 truncate
清除数据的第二种方法:截断表
语法:
sql
TRUNCATE [TABLE] table_name

trucnate只能对整表进行操作,不能像delete一样针对部分数据进行操作。
此外,trucnate不会把自己包装成事务,不会把自己的操作记录记录到mysql的日志中,所以truncate在删除数据时比delete快,但是也正是由于它不会把自己的操作记录记录到mysql的日志中,所以这个语句不能回滚。
同时,截断表在删除数据的同时会重置auto_increment项
在截断表t1前auto_increment的值为6

截断后auto_increment的值就被重置了,所以我们在查看创建表的语句时就查不到这一项的值了:

前面提到过我们可以在查询时添加distinct字段来去除查询结果中重复的值,但是当我们要删除表中重复的数据时,可以像下面这样做:
首先建立一个列属性和原表一模一样的新表,然后查找去重并插入到新表中,然后重命名
这个操作与distinct有明显不同,distinct是去除查询结果中的数据,相当于select查询就是建立了一个新的表,而删除表中重复的数据是为了改变原表中的数据。
修改前的表:

首先建立一个新表:

然后将去重后的查询结果插入到新表中:

修改表名:

修改完成后的表:

二、聚合函数
在查询时通常会配合一些聚合函数使用,常用的聚合函数有下面这些:
| 函数 | 说明 |
|---|---|
COUNT([DISTINCT] expr) |
返回查询到的数据的数量 |
SUM([DISTINCT] expr) |
返回查询到的数据的总和,不是数字没有意义 |
AVG([DISTINCT] expr) |
返回查询到的数据的平均值,不是数字没有意义 |
MAX([DISTINCT] expr) |
返回查询到的数据的最大值,不是数字没有意义 |
MIN([DISTINCT] expr) |
返回查询到的数据的最小值,不是数字没有意义 |
聚合统计使用示例:
COUNT([DISTINCT] expr):

SUM([DISTINCT] expr):

AVG([DISTINCT] expr):

MAX([DISTINCT] expr):

MIN([DISTINCT] expr):

三、分组聚合统计
3.1 group by
使用group by 语句可以对查询的数据进行分组。分组的目的是为了在进行分组之后,方便进行聚合统计。使用示例如下:
显示每种产品的最贵商品价格和平均商品价格

GROUP BY 分组的逻辑是:指定列名,就会拿这一列不同的值来划分分组。以 category 商品类别分组举例,同一个分组里面 category 的值一定是相同的,这一列可以直接跟着聚合结果一起输出。分组本质上就是把一张表,在逻辑上拆成多个子表,之后分别对每一个子表做聚合统计。
分组聚合统计的执行顺序是先分组,再聚合。group by 后面可以跟多个列联合分组,select 里写的普通列,必须是 group by 分组里出现过的列,否则会报错。

3.2 having
分完组得到聚合统计的结果之后,我们可以使用having对结果进行判断:

显示平均订单金额低于1000的用户和他的平均订单金额,李四不参与统计

虽然where和having在语义上是相同的,但是在select中不推荐使用having,需要将二者区分开
3.3 where和having的区别
WHERE 是在 GROUP BY 之前对原始数据行做筛选,不能使用聚合函数 ;HAVING 是在 GROUP BY 完成分组之后,针对分组聚合后的结果做筛选,支持写聚合函数。简单来说,where 针对原始表的任意列过滤数据,having 针对分组聚合之后的结果过滤,二者执行的筛选阶段不一样。
另外要记住,不是只有磁盘上真实存在的表才叫表,一条 select 查询出来的结果集,本质上也可以看作一张表。理解这点之后,只要掌握好单表的增删查改,绝大多数 SQL 场景都可以用这套思路去处理。