【MySQL】8. 基本查询(update/delete/聚合/分组)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 【MySQL】8. 基本查询(update/delete/聚合/分组)

表的删改

3. Update

语法:

UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]

对查询到的结果进行列值更新
案例:

3.1 将孙悟空同学的数学成绩变更为 80 分

-- 更新值为具体值
-- 查看原数据
SELECT name, math FROM exam_result WHERE name = '孙悟空';
+-------+----+
| name  |math|
+-------+----+
| 孙悟空 | 78 |
+-------+----+
1 row in set (0.00 sec)

-- 数据更新
UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0

-- 查看更新后数据
SELECT name, math FROM exam_result WHERE name = '孙悟空';
+-------+----+
| name  |math|
+-------+----+
| 孙悟空 | 80 |
+-------+----+
1 row in set (0.00 sec)

3.2 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分

-- 一次更新多个列

-- 查看原数据
SELECT name, math, chinese FROM exam_result WHERE name = '曹孟德';
+-------+----+-------+
| name  |math|chinese|
+-------+----+-------+
| 曹孟德 | 84 |    82 |
+-------+----+-------+
1 row in set (0.00 sec)

-- 数据更新
UPDATE exam_result SET math = 60, chinese = 70 WHERE name = '曹孟德';
Query OK, 1 row affected (0.14 sec)
Rows matched: 1 Changed: 1 Warnings: 0

-- 查看更新后数据
SELECT name, math, chinese FROM exam_result WHERE name = '曹孟德';
+-------+----+-------+
| name  |math|chinese|
+-------+----+-------+
| 曹孟德 | 60 |   70  |
+-------+----+-------+
1 row in set (0.00 sec)

3.3 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分

-- 更新值为原值基础上变更
-- 查看原数据
-- 别名可以在ORDER BY中使用
SELECT name, math, chinese + math + english 总分 FROM exam_result ORDER BY 总分 LIMIT 3;
+-------+----+-----+
| name  |math| 总分 |
+-------+----+-----+
| 宋公明 | 65 | 170 |
| 刘玄德 | 85 | 185 |
| 曹孟德 | 60 | 197 |
+-------+----+-----+
3 rows in set (0.00 sec)

-- 数据更新,不支持 math += 30 这种语法
UPDATE exam_result SET math = math + 30 ORDER BY chinese + math + english LIMIT 3;
-- 查看更新后数据
-- 思考:这里还可以按总分升序排序取前 3 个么?
SELECT name, math, chinese + math + english 总分 FROM exam_result WHERE name IN ('宋公明', '刘玄德', '曹孟德');
+-------+----+-----+
| name  |math| 总分 |
+-------+----+-----+
| 曹孟德 | 90 | 227 |
| 刘玄德 |115 | 215 |
| 宋公明 | 95 | 200 |
+-------+----+-----+
3 rows in set (0.00 sec)

-- 按总成绩排序后查询结果
SELECT name, math, chinese + math + english 总分 FROM exam_result ORDER BY 总分 LIMIT 3;
+-------+----+-----+
| name  |math| 总分 |
+-------+----+-----+
| 宋公明 | 95 | 200 |
| 刘玄德 |115 | 215 |
| 唐三藏 | 98 | 221 |
+-------+----+-----+
3 rows in set (0.00 sec)

3.4 将所有同学的语文成绩更新为原来的 2 倍

==注意:更新全表的语句慎用!==

-- 没有 WHERE 子句,则更新全表

-- 查看原数据
SELECT * FROM exam_result;
+---+-------+-------+----+-------+
| id|  name |chinese|math|english|
+---+-------+-------+----+-------+
| 1 | 唐三藏 |    67 | 98 |    56 |
| 2 | 孙悟空 |    87 | 80 |    77 |
| 3 | 猪悟能 |    88 | 98 |    90 |
| 4 | 曹孟德 |    70 | 90 |    67 |
| 5 | 刘玄德 |    55 | 115|    45 |
| 6 | 孙权   |    70 | 73 |    78 |
| 7 | 宋公明 |    75 | 95 |    30 |
+---+-------+-------+----+-------+
7 rows in set (0.00 sec)

-- 数据更新
UPDATE exam_result SET chinese = chinese * 2;
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7 Changed: 7 Warnings: 0

-- 查看更新后数据
SELECT * FROM exam_result;
+---+-------+-------+----+--------+
| id|  name |chinese|math|english |
+---+-------+-------+----+--------+
| 1 | 唐三藏 |   134 | 98 |     56 |
| 2 | 孙悟空 |   174 | 80 |     77 |
| 3 | 猪悟能 |   176 | 98 |     90 |
| 4 | 曹孟德 |   140 | 90 |     67 |
| 5 | 刘玄德 |   110 |115 |     45 |
| 6 | 孙权   |   140 | 73 |     78 |
| 7 | 宋公明 |   150 | 95 |     30 |
+---+-------+-------+----+--------+
7 rows in set (0.00 sec)

4. Delete

4.1 删除数据

语法:

DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]

案例:

4.1.1 删除孙悟空同学的考试成绩

-- 查看原数据
SELECT * FROM exam_result WHERE name = '孙悟空';
+---+-------+-------+----+-------+
| id|  name |chinese|math|english|
+---+-------+-------+----+-------+
| 2 | 孙悟空 |   174 | 80 |    77 |
+---+-------+-------+----+-------+
1 row in set (0.00 sec)

-- 删除数据
DELETE FROM exam_result WHERE name = '孙悟空';
Query OK, 1 row affected (0.17 sec)

-- 查看删除结果
SELECT * FROM exam_result WHERE name = '孙悟空';
Empty set (0.00 sec)

4.1.2 删除整张表数据

注意:删除整表操作要慎用!

-- 准备测试表
CREATE TABLE for_delete (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
Query OK, 0 rows affected (0.16 sec)

-- 插入测试数据
INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');
Query OK, 3 rows affected (1.05 sec)
Records: 3 Duplicates: 0 Warnings: 0

-- 查看测试数据
SELECT * FROM for_delete;
+---+----+
| id|name|
+---+----+
| 1 |  A |
| 2 |  B |
| 3 |  C |
+---+----+
3 rows in set (0.00 sec)
-- 删除整表数据
DELETE FROM for_delete;
Query OK, 3 rows affected (0.00 sec)

-- 查看删除结果
SELECT * FROM for_delete;
Empty set (0.00 sec)
-- 再插入一条数据,自增 id 在原值上增长
INSERT INTO for_delete (name) VALUES ('D');
Query OK, 1 row affected (0.00 sec)

-- 查看数据
SELECT * FROM for_delete;
+----+------+
| id | name |
+----+------+
| 4 | D |
+----+------+
1 row in set (0.00 sec)

-- 查看表结构,会有 AUTO_INCREMENT=n 项
SHOW CREATE TABLE for_delete\G
*************************** 1. row ***************************
Table: for_delete
Create Table: CREATE TABLE `for_delete` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

知识拓展:
在这里插入图片描述

4.2 截断表

语法:

TRUNCATE [TABLE] table_name

==注意:这个操作慎用==

  1. 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
  2. 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事
    物,所以无法回滚
  3. 会重置 AUTO_INCREMENT 项
-- 准备测试表
CREATE TABLE for_truncate (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
Query OK, 0 rows affected (0.16 sec)

-- 插入测试数据
INSERT INTO for_truncate (name) VALUES ('A'), ('B'), ('C');
Query OK, 3 rows affected (1.05 sec)
Records: 3 Duplicates: 0 Warnings: 0

-- 查看测试数据
SELECT * FROM for_truncate;
+---+----+
| id|name|
+---+----+
| 1 |  A |
| 2 |  B |
| 3 |  C |
+---+----+
3 rows in set (0.00 sec)
-- 截断整表数据,注意影响行数是 0,所以实际上没有对数据真正操作
TRUNCATE for_truncate;
Query OK, 0 rows affected (0.10 sec)

-- 查看删除结果
SELECT * FROM for_truncate;
Empty set (0.00 sec)

-- 再插入一条数据,自增 id 在重新增长
INSERT INTO for_truncate (name) VALUES ('D');
Query OK, 1 row affected (0.00 sec)

-- 查看数据
SELECT * FROM for_truncate;
+---+----+
| id|name|
+---+----+
| 1 |  D |
+---+----+
1 row in set (0.00 sec)

-- 查看表结构,会有 AUTO_INCREMENT=2 项
SHOW CREATE TABLE for_truncate\G
*************************** 1. row ***************************
Table: for_truncate
Create Table: CREATE TABLE `for_truncate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

5. 插入查询结果

语法:

INSERT INTO table_name [(column [, column ...])] SELECT ...

案例:删除表中的的重复复记录,重复的数据只能有一份

-- 创建原数据表
CREATE TABLE duplicate_table (id int, name varchar(20));
Query OK, 0 rows affected (0.01 sec)

-- 插入测试数据
INSERT INTO duplicate_table VALUES
(100, 'aaa'),
(100, 'aaa'),
(200, 'bbb'),
(200, 'bbb'),
(200, 'bbb'),
(300, 'ccc');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0

思路:
在这里插入图片描述
为啥最后通过rename方式进行呢? -- 就是等一切数据就绪再进行统一放入/更新/生效
不先进行rename再插入呢? -- MySQL当中rename的效率是非常高效的,插入是十分低效的而且也不安全(万一在插入的过程中断点丢失数据是非常危险的)

-- 查看最终结果
SELECT * FROM duplicate_table;
+----+-----+
| id | name|
+----+-----+
| 100| aaa |
| 200| bbb |
| 300| ccc |
+----+-----+
3 rows in set (0.00 sec)

6. 聚合函数

+-------------------------+------------------------------------+ 
|            函数          |                  说明               |
+-------------------------+------------------------------------+ 
| COUNT([DISTINCT] expr)  | 返回查询到的数据的 数量                |
| SUM([DISTINCT] expr)    | 返回查询到的数据的 总和,不是数字没有意义  |
| AVG([DISTINCT] expr)    | 返回查询到的数据的 平均值,不是数字没有意义|
| MAX([DISTINCT] expr)    | 返回查询到的数据的 最大值,不是数字没有意义|
| MIN([DISTINCT] expr)    | 返回查询到的数据的 最小值,不是数字没有意义|
+-------------------------+------------------------------------+

案例:

6.1 统计班级共有多少同学

-- 使用 * 做统计,不受 NULL 影响
SELECT COUNT(*) FROM students;
+----------+
| COUNT(*) |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)
-- 使用表达式做统计
SELECT COUNT(1) FROM students;
+----------+
| COUNT(1) |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)

6.2 统计班级收集的 qq 号有多少

-- NULL 不会计入结果
SELECT COUNT(qq) FROM students;
+-----------+
| COUNT(qq) |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

6.3 统计本次考试的数学成绩分数个数

-- COUNT(math) 统计的是全部成绩
SELECT COUNT(math) FROM exam_result;
+-------------+
| COUNT(math) |
+-------------+
|           6 |
+-------------+
1 row in set (0.00 sec)

-- COUNT(DISTINCT math) 统计的是去重成绩数量
SELECT COUNT(DISTINCT math) FROM exam_result;
+----------------------+
| COUNT(DISTINCT math) |
+----------------------+
|                    5 |
+----------------------+
1 row in set (0.00 sec)

6.4 统计数学成绩总分

SELECT SUM(math) FROM exam_result;
+-----------+
| SUM(math) |
+-----------+
|       569 |
+-----------+
1 row in set (0.00 sec)
-- 不及格 < 60 的总分,没有结果,返回 NULL
SELECT SUM(math) FROM exam_result WHERE math < 60;
+-----------+
| SUM(math) |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)

6.4 统计平均总分

SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;
+---------+
| 平均总分 |
+---------+
|   297.5 |
+---------+

6.5 返回英语最高分

SELECT MAX(english) FROM exam_result;
+-------------+
| MAX(english)|
+-------------+
|          90 |
+-------------+
1 row in set (0.00 sec)

6.6 返回 > 70 分以上的数学最低分

SELECT MIN(math) FROM exam_result WHERE math > 70;
+-----------+
| MIN(math) |
+-----------+
|        73 |
+-----------+
1 row in set (0.00 sec)

7. group by子句的使用

在select中使用group by 子句可以对指定列进行分组查询

select column1, column2, .. from table group by column;

案例:
准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)
这里我将雇员信息表放在gitee上,点击这里即可!!!

  • EMP员工表
  • DEPT部门表
  • SALGRADE工资等级表

下载到本地上之后导入到云服务的MySQL数据目录下:

-rw-r--r-- 1 root  root    3878 Mar 25  2022 scott_data.sql

[root@iZ0jl69kyvg0h181cozuf5Z tt]# pwd
/var/lib/mysql/tt
这里tt是我自己建的数据库(自己选择路径)

将数据库还原出来:

mysql> source /var/lib/mysql/tt/scott_data.sql
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Database changed
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

Query OK, 1 row affected (0.01 sec)

对应的/var/lib/mysql下同样出现对应的数据库内容文件

[root@iZ0jl69kyvg0h181cozuf5Z mysql]# pwd
/var/lib/mysql
[root@iZ0jl69kyvg0h181cozuf5Z mysql]# ll
drwxr-x--- 2 mysql mysql     4096 Mar 21 09:30 scott

7.1 显示每个部门的平均工资和最高工资

在这里插入图片描述
在这里插入图片描述

7.2 显示每个部门的每种岗位的平均工资和最低工资

mysql> select deptno,job, min(sal) 最低,avg(sal) 平均 from emp group by deptno,job;
+--------+-----------+---------+-------------+
| deptno | job       | 最低    | 平均        |
+--------+-----------+---------+-------------+
|     10 | CLERK     | 1300.00 | 1300.000000 |
|     10 | MANAGER   | 2450.00 | 2450.000000 |
|     10 | PRESIDENT | 5000.00 | 5000.000000 |
|     20 | ANALYST   | 3000.00 | 3000.000000 |
|     20 | CLERK     |  800.00 |  950.000000 |
|     20 | MANAGER   | 2975.00 | 2975.000000 |
|     30 | CLERK     |  950.00 |  950.000000 |
|     30 | MANAGER   | 2850.00 | 2850.000000 |
|     30 | SALESMAN  | 1250.00 | 1400.000000 |
+--------+-----------+---------+-------------+
9 rows in set (0.00 sec)

7.3 显示平均工资低于2000的部门和它的平均工资

统计各个部门的平均工资

select avg(sal) from EMP group by deptno

having和group by配合使用,对group by结果进行过滤

select deptno,avg(sal) 平均 from EMP group by deptno having myavg<2000;
+--------+-------------+
| deptno | 平均        |
+--------+-------------+
|     30 | 1566.666667 |
+--------+-------------+
1 row in set (0.00 sec)

--having经常和group by搭配使用,作用是对分组进行筛选,作用有些像where

7.4 SMITH员工不参与计算,显示平均工资低于2000的岗位和它的平均工资

mysql> select deptno,job,avg(sal) 平均 from emp where ename !='SMITH' group by deptno,job having avg(sal) < 2000;+--------+----------+-------------+
| deptno | job      | 平均        |
+--------+----------+-------------+
|     10 | CLERK    | 1300.000000 |
|     20 | CLERK    | 1100.000000 |
|     30 | CLERK    |  950.000000 |
|     30 | SALESMAN | 1400.000000 |
+--------+----------+-------------+
4 rows in set (0.00 sec)

在这里插入图片描述

切屏小技巧:
在这里插入图片描述

练习题

在进行练习之前,请务必熟悉两篇博客当中的内容并且动手实践!!!

1. SQL195 查找最晚入职员工的所有信息

在这里插入图片描述

2. SQL196 查找入职员工时间排名倒数第三的员工所有信息

在这里插入图片描述

3. SQL201 查找薪水记录超过15条的员工号emp_no以及其对应的记录次数t

4. 182. 查找重复的电子邮箱

5. 595. 大国

6. 177. 第N高薪

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
181 66
|
6天前
|
存储 Oracle 关系型数据库
索引在手,查询无忧:MySQL索引简介
MySQL 是一款广泛使用的关系型数据库管理系统,在2024年5月的DB-Engines排名中得分1084,仅次于Oracle。本文介绍MySQL索引的工作原理和类型,包括B+Tree、Hash、Full-text索引,以及主键、唯一、普通索引等,帮助开发者优化查询性能。索引类似于图书馆的分类系统,能快速定位数据行,极大提高检索效率。
32 8
|
9天前
|
SQL 关系型数据库 MySQL
MySQL 窗口函数详解:分析性查询的强大工具
MySQL 窗口函数从 8.0 版本开始支持,提供了一种灵活的方式处理 SQL 查询中的数据。无需分组即可对行集进行分析,常用于计算排名、累计和、移动平均值等。基本语法包括 `function_name([arguments]) OVER ([PARTITION BY columns] [ORDER BY columns] [frame_clause])`,常见函数有 `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `SUM()`, `AVG()` 等。窗口框架定义了计算聚合值时应包含的行。适用于复杂数据操作和分析报告。
51 11
|
13天前
|
存储 关系型数据库 MySQL
mysql怎么查询longblob类型数据的大小
通过本文的介绍,希望您能深入理解如何查询MySQL中 `LONG BLOB`类型数据的大小,并结合优化技术提升查询性能,以满足实际业务需求。
46 6
|
3天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
13 3
|
3天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
20 3
|
3天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
25 2
|
17天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
120 15
|
10天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
17天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。