MySQL数据库(18):高级数据操作-查询数据

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL数据库(18):高级数据操作-查询数据

高级数据操作-查询数据

完整的查询指令


select 选项 字段列表 
from 数据源 
-- 5子句
where 条件 
group by 分组 
having 条件 
order by 排序 
limit 限制;

1、select选项

处理查询到的结果


all 默认值,表示保存所有记录

distinct 去重,只保留一条(所有字段都相同认为重复)

create table my_select(
    name varchar(10)
);
insert into my_select (name) values ('A'), ('A'), ('A'), ('B');
mysql> select all * from my_select;
+------+
| name |
+------+
| A    |
| A    |
| A    |
| B    |
+------+
mysql> select distinct * from my_select;
+------+
| name |
+------+
| A    |
| B    |
+------+

2、字段列表

多张表获取数据,可能存在不同表中有同名字段,需要使用别名alias


字段名 [as] 字段别名;
select distinct name as name1, name as name2 from my_select;
+-------+-------+
| name1 | name2 |
+-------+-------+
| A     | A     |
| B     | B     |
+-------+-------+

3、from数据源

为前面的查询提供数据


数据源只要是一个符合二维表结构的数据即可


3.1、单表数据

from 表名;
select * from my_select;

3.2、多表数据

基本语法


from 表名1, 表名2...;
mysql> select * from my_select;
+------+
| name |
+------+
| A    |
| B    |
+------+
2 rows in set (0.00 sec)
mysql> select * from my_student;
+----+--------+
| id | name   |
+----+--------+
|  1 | 刘备   |
|  2 | 李四   |
|  3 | 王五   |
+----+--------+
3 rows in set (0.00 sec)
mysql> select * from my_select, my_student;
+------+----+--------+
| name | id | name   |
+------+----+--------+
| A    |  1 | 刘备   |
| B    |  1 | 刘备   |
| A    |  2 | 李四   |
| B    |  2 | 李四   |
| A    |  3 | 王五   |
| B    |  3 | 王五   |
+------+----+--------+
6 rows in set (0.00 sec)

结果是两张表记录数据相乘,字段数拼接


本质:从第一张表取出一条记录,去拼凑第二张表所有记录,保留所有结果


笛卡尔积,会给数据库造成压力,尽量避免


3.3、动态数据

from后面不是一个实体表,而是一个从表中查询出来得到的二维结果表(子查询)


基本语法


from (select 字段列表 from 表名) as 别名
mysql> select * from (select * from my_student) as t1;
+----+--------+
| id | name   |
+----+--------+
|  1 | 刘备   |
|  2 | 李四   |
|  3 | 王五   |
+----+--------+

4、Where条件

通过运算符进行结果比较,来判断符合条件的数据


5、Group by分组

根据指定的字段,将数据进行分组,分组的目的是为了统计


5.1、分组统计

group by 字段名

分组后,只保留每组的第一条数据


mysql> select * from my_student;
+----+--------+----------+
| id | name   | class_id |
+----+--------+----------+
|  1 | 刘备   |        1 |
|  2 | 李四   |        1 |
|  3 | 王五   |        2 |
+----+--------+----------+
mysql> select  class_id  from my_student group by class_id;
+----------+
| class_id |
+----------+
|        1 |
|        2 |
+----------+

5.2、聚合函数

count() 统计数量。如果是字段,不统计null字段

avg 平均值

sum 求和

max 最大值

min 最小值

group_concat 分组中指定字段拼接

按照班级统计每班人数,最大年龄,最小年龄,平均年龄


mysql> select * from my_student;
+----+--------+----------+------+
| id | name   | class_id | age  |
+----+--------+----------+------+
|  1 | 刘备   |        1 |   18 |
|  2 | 李四   |        1 |   19 |
|  3 | 王五   |        2 |   20 |
+----+--------+----------+------+
mysql> select class_id, count(*), max(age), min(age), avg(age) from my_student group by class_id;
+----------+----------+----------+----------+----------+
| class_id | count(*) | max(age) | min(age) | avg(age) |
+----------+----------+----------+----------+----------+
|        1 |        2 |       19 |       18 |  18.5000 |
|        2 |        1 |       20 |       20 |  20.0000 |
+----------+----------+----------+----------+----------+
mysql> select class_id, group_concat(name), count(*), max(age), min(age), avg(age) from my_student group by class_id;
+----------+--------------------+----------+----------+----------+----------+
| class_id | group_concat(name) | count(*) | max(age) | min(age) | avg(age) |
+----------+--------------------+----------+----------+----------+----------+
|        1 | 刘备,李四          |        2 |       19 |       18 |  18.5000 |
|        2 | 王五               |        1 |       20 |       20 |  20.0000 |
+----------+--------------------+----------+----------+----------+----------+

5.3、多分组

对已分组的数据进行再次分组


基本语法


-- 按照字段1进行分组,将结果再按照字段2进行分组
group by 字段1, 字段2;
mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  4 | 张飞   |        2 |   21 |      1 |
|  5 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+
mysql> select class_id, gender, count(*), group_concat(name) from my_student group by class_id, gender;
+----------+--------+----------+--------------------+
| class_id | gender | count(*) | group_concat(name) |
+----------+--------+----------+--------------------+
|        1 |      1 |        1 | 李四               |
|        1 |      2 |        2 | 刘备,关羽          |
|        2 |      1 |        1 | 张飞               |
|        2 |      2 |        1 | 王五               |
+----------+--------+----------+--------------------+

5.4、分组排序

按照分组字段排序,默认升序


-

- 班级升序,性别降序 
-- mysql8.012之后,不支持group by 排序,需要使用order by排序
select class_id, gender, count(*), group_concat(name) 
from my_student 
group by class_id, gender 
order by class_id asc, gender desc;
+----------+--------+----------+--------------------+
| class_id | gender | count(*) | group_concat(name) |
+----------+--------+----------+--------------------+
|        1 |      2 |        2 | 刘备,关羽          |
|        1 |      1 |        1 | 李四               |
|        2 |      2 |        1 | 王五               |
|        2 |      1 |        1 | 张飞               |
+----------+--------+----------+--------------------+

5.5、回溯排序

统计过程中层层上报


group by 字段 with rollup;
-- 分组
mysql> select class_id, count(*) from my_student group by class_id;
+----------+----------+
| class_id | count(*) |
+----------+----------+
|        1 |        3 |
|        2 |        2 |
+----------+----------+
-- 分组回溯
mysql> select class_id, count(*) from my_student group by class_id with rollup;
+----------+----------+
| class_id | count(*) |
+----------+----------+
|        1 |        3 |
|        2 |        2 |
|     NULL |        5 |
+----------+----------+
-- 多分组
mysql> select class_id, gender, count(*) from my_student group by class_id, gender;
+----------+--------+----------+
| class_id | gender | count(*) |
+----------+--------+----------+
|        1 |      2 |        2 |
|        1 |      1 |        1 |
|        2 |      2 |        1 |
|        2 |      1 |        1 |
+----------+--------+----------+
-- 多分组回溯
mysql> select class_id, gender, count(*) from my_student group by class_id, gender with rollup;
+----------+--------+----------+
| class_id | gender | count(*) |
+----------+--------+----------+
|        1 |      1 |        1 |
|        1 |      2 |        2 |
|        1 |   NULL |        3 |
|        2 |      1 |        1 |
|        2 |      2 |        1 |
|        2 |   NULL |        2 |
|     NULL |   NULL |        5 |
+----------+--------+----------+

6、having条件

和where一样,用来进行数据条件筛选


区别:


where是从表中取数据,where将数据从磁盘拿到内存,where之后的操作都是内存操作

having聚合之后的数据中取数据

用在group by分组之后,可以针对分组数据进行统计筛选


mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
|  8 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+
-- 查询班级人数大于等于3以上的班级
mysql> select class_id, count(*) as total 
from my_student 
group by class_id 
having total >= 3;
+----------+-------+
| class_id | total |
+----------+-------+
|        1 |     3 |
+----------+-------+

7、order by排序

7.1、单字段排序

基本语法


-- 默认asc升序,desc降序
order by 字段 [asc|desc]
-- 按照年龄降序排序
mysql> select * from my_student order by age asc;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
|  8 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+

7.2、多字段排序

基本语法


order by 字段1, 字段2... [asc|desc];
-- 按照班级和年龄排序
mysql> select * from my_student order by class_id, age desc;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  8 | 关羽   |        1 |   22 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  1 | 刘备   |        1 |   18 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
+----+--------+----------+------+--------+

8、limit 限制

限制记录数数量,如果数量不够,仅返回剩余数据


8.1、记录数限制

基本语法


limit 数量;
mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
|  8 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+
mysql> select * from my_student limit 2;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
+----+--------+----------+------+--------+

8.2、分页

获取指定区间的数据


基本语法


limit 偏移量, 数量;
-- 等价于
limit 数量 offset 偏移量;

MySQL下标从0开始


分页计算公式:


page: 页数
size: 每页数量
偏移量 = (page - 1) * size
mysql> select * from my_student;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
|  3 | 王五   |        2 |   20 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
|  8 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+
-- 每页2条数据,获取第1页 (1 - 1) * 2, 2
mysql> select * from my_student limit 0, 2;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  1 | 刘备   |        1 |   18 |      2 |
|  2 | 李四   |        1 |   19 |      1 |
+----+--------+----------+------+--------+
-- 每页2条数据,获取第2页 (2 - 1) * 2, 2
mysql> select * from my_student limit 2, 2;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  3 | 王五   |        2 |   20 |      2 |
|  7 | 张飞   |        2 |   21 |      1 |
+----+--------+----------+------+--------+
-- 每页3条数据,获取第2页 (3 - 1) * 2, 2
mysql> select * from my_student limit 4, 2;
+----+--------+----------+------+--------+
| id | name   | class_id | age  | gender |
+----+--------+----------+------+--------+
|  8 | 关羽   |        1 |   22 |      2 |
+----+--------+----------+------+--------+
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
58
分享
相关文章
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
48 28
让数据与AI贴得更近,阿里云瑶池数据库系列产品焕新升级
4月9日阿里云AI势能大会上,阿里云瑶池数据库发布重磅新品及一系列产品能力升级。「推理加速服务」Tair KVCache全新上线,实现KVCache动态分层存储,显著提高内存资源利用率,为大模型推理降本提速。
数据库数据删除策略:硬删除vs软删除的最佳实践指南
在项目开发中,“删除”操作常见但方式多样,主要分为硬删除与软删除。硬删除直接从数据库移除数据,操作简单、高效,但不可恢复;适用于临时或敏感数据。软删除通过标记字段保留数据,支持恢复和审计,但增加查询复杂度与数据量;适合需追踪历史或可恢复的场景。两者各有优劣,实际开发中常结合使用以满足不同需求。
32 4
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
本文探讨了在使用YMP 23.2.1.3迁移MySQL Server字符集为latin1的中文数据至YashanDB时出现乱码的问题。问题根源在于MySQL latin1字符集存放的是实际utf8编码的数据,而YMP尚未支持此类场景。文章提供了两种解决方法:一是通过DBeaver直接迁移表数据;二是将MySQL表数据转换为Insert语句后手动插入YashanDB。同时指出,这两种方法适合单张表迁移,多表迁移可能存在兼容性问题,建议对问题表单独处理。
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
【YashanDB知识库】数据库用户所拥有的权限查询
【YashanDB知识库】数据库用户所拥有的权限查询
|
26天前
|
百万指标,秒级查询,零宕机——时序数据库 TDengine 在 AIOps 中的硬核实战
本篇文章详细讲述了七云团队在运维平台中如何利用 TDengine 解决海量时序数据存储与查询的实际业务需求。内容涵盖了从数据库选型、方案落地到业务挑战及解决办法的完整过程,特别是分享了升级 TDengine 3.x 时的实战经验,给到有需要的小伙伴参考阅读。
53 1
WordPress数据库查询缓存插件
这款插件通过将MySQL查询结果缓存至文件、Redis或Memcached,加速页面加载。它专为未登录用户优化,支持跨页面缓存,不影响其他功能,且可与其他缓存插件兼容。相比传统页面缓存,它仅缓存数据库查询结果,保留动态功能如阅读量更新。提供三种缓存方式选择,有效提升网站性能。
42 1
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,
【YashanDB知识库】python驱动查询gbk字符集崖山数据库CLOB字段,数据被驱动截断
【YashanDB知识库】python驱动查询gbk字符集崖山数据库CLOB字段,数据被驱动截断
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等