MySQL基本查询

文章目录

    • [1. create](#1. create)
      • [1.1 单行数据 + 全列插入](#1.1 单行数据 + 全列插入)
      • [1.2 多行数据 + 指定列插入](#1.2 多行数据 + 指定列插入)
      • [1.3 插入更新](#1.3 插入更新)
      • [1.4 插入替换](#1.4 插入替换)
    • [2. retrieve](#2. retrieve)
      • [2.1 select列](#2.1 select列)
        • [2.11 全列查询](#2.11 全列查询)
        • [2.12 指定列查询](#2.12 指定列查询)
        • [2.13 查询字段为表达式](#2.13 查询字段为表达式)
        • [2.14 结果去重](#2.14 结果去重)
      • [2.2 where条件](#2.2 where条件)
        • [2.21 各种成绩查询](#2.21 各种成绩查询)
        • [2.22 null的查询](#2.22 null的查询)
      • [2.3 结果排序](#2.3 结果排序)
      • [2.4 筛选分页结果](#2.4 筛选分页结果)
    • [3. update](#3. update)
    • [4. delete](#4. delete)
    • [5. 插入查询结果](#5. 插入查询结果)
    • [6. 聚合函数](#6. 聚合函数)
      • [6.1 无分组聚合](#6.1 无分组聚合)
      • [6.2 分组聚合](#6.2 分组聚合)

1. create

语法:

mysql 复制代码
insert [into] table_name [(column [, column] ...)] values (value_list) [, (values_list)]...

[]里面的内容可以省略,values两侧平衡(可理解为扁担),左侧表示要向哪列插入,右侧表示插入的数据

1.1 单行数据 + 全列插入

创建一个学生表:

mysql 复制代码
mysql> create table students (
    -> id int unsigned primary key auto_increment,
    -> sn int unsigned unique key,
    -> name varchar(20) not null,
    -> telephone varchar(32) unique key
    -> );

一次插入一行数据:

mysql 复制代码
mysql> insert into students(sn, name, telephone) values (23402101, '张三', '2024001');
mysql> insert into students values (10, 23402110, '李四', '2024010');	# 全列插入

values左侧忽略时就表明要进行全列插入,每一列都要指定数据

1.2 多行数据 + 指定列插入

mysql 复制代码
mysql> insert into students values (11, 23402111, '王五', '2024011'), (12, 23402112, '赵六', '2024012');

values右侧用逗号隔开,表明插入多行数据

1.3 插入更新

mysql 复制代码
mysql> insert into students values (12, 23402122, '田七', '2024022');	#主键冲突
ERROR 1062 (23000): Duplicate entry '12' for key 'PRIMARY'
mysql> insert into students values (13, 23402113, '田七', '2024012');	# 唯一键冲突
ERROR 1062 (23000): Duplicate entry '2024012' for key 'telephone'

当插入时出现冲突的时候,可采用同步更新操作,语法:

mysql 复制代码
insert into  ... on duplicate key update column = value [, column = value] ...
mysql 复制代码
mysql> insert into students values (12, 23402122, '田七', '2024022') 
    -> on duplicate key update sn=23402122, name='田七', telephone='202422';

-- 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
-- 1 row affected: 表中没有冲突数据,数据被插入
-- 2 row affected: 表中有冲突数据,并且数据已经被更新

可采用select row_count()查看受影响的行数

1.4 插入替换

如果主键或者唯一键没有冲突,则直接插入;

如果主键或者唯一键冲突,先删除,再插入:

mysql 复制代码
mysql> replace into students (sn, name, telephone) values (234021015, '老八',  2024015);
Query OK, 1 row affected (0.01 sec)

mysql> replace into students (sn, name, telephone) values (234021015, '小八',  2024015);
Query OK, 2 rows affected (0.00 sec)

2. retrieve

mysql 复制代码
mysql> create table exam_ret(
    -> id int unsigned primary key auto_increment,
    -> name varchar(20) not null,
    -> chinese float default 0.0 comment '语文成绩',
    -> math float default 0.0 comment '数学成绩',
    -> english float default 0.0 comment '英语成绩'
    -> );
mysql> insert into exam_ret (name, chinese, math, english) values 
    -> ('张三', 88, 84, 77),
    -> ('李四', 75, 91, 66),
    -> ('王五', 45, 82, 73),
    -> ('赵六', 94, 42, 51),
    -> ('田七', 62, 67, 98);

2.1 select列

2.11 全列查询
mysql 复制代码
mysql> select * from exam_ret;

*表示通配,在实际并不推荐采用*进行全列查询

  1. 数据库服务一般在服务器上;
  2. 线上服务器数据库里面存储的数据量非常大
2.12 指定列查询
mysql 复制代码
mysql> select name, math from exam_ret;
2.13 查询字段为表达式
mysql 复制代码
mysql> select name, math, chinese+math+english from exam_ret;

也可也将表达式名称命名

mysql 复制代码
mysql> select name, math, chinese+math+english as total from exam_ret;
mysql 复制代码
mysql> select name 姓名, math 数学, chinese+math+english 总分 from exam_ret;
2.14 结果去重
mysql 复制代码
mysql> select distinct chinese from exam_ret;

2.2 where条件

比较运算符:

运算符 说明
>, >=, <, <= 大于,大于等于,小于,小于等于
= 等于,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 个)任意字符;_ 表示任意一个字符

逻辑运算符:

运算符 说明
AND 多个条件必须都为 TRUE(1),结果才是 TRUE(1)
OR 任意一个条件为 TRUE(1), 结果为 TRUE(1)
NOT 条件为 TRUE(1),结果为 FALSE(0)
2.21 各种成绩查询

++查找成绩不及格的同学:++

mysql 复制代码
mysql> select name, chinese from exam_ret where chinese<60;
mysql> select name, math from exam_ret where math<60;
mysql> select name, english from exam_ret where english<60;

++查找语文成绩在[80,100]的同学:++

mysql 复制代码
mysql> select name, chinese from exam_ret where chinese>=80 and chinese<=100;
mysql> select name, chinese from exam_ret where chinese between 80 and 100;

++查找指定英语成绩:++

mysql 复制代码
mysql> select name, english from exam_ret where english=98 or english=97 or english=51;
mysql> select name, english from exam_ret where english in (98, 97, 51);

++查找姓张和张某:++

mysql 复制代码
mysql> select name from exam_ret where name like '张%';	#姓孙
mysql> select name from exam_ret where name like '张_';	#孙某

++查找英文成绩好于英语成绩的同学:++

mysql 复制代码
mysql> select name, chinese, english from exam_ret where chinese > english;

++查找总分小于225的同学:++

mysql 复制代码
mysql> select name, chinese + math + english total from exam_ret where total<225;
ERROR 1054 (42S22): Unknown column 'total' in 'where clause'

在上面的sql语句中,执行顺序是:

  1. 先执行from,要知道在哪个表当中筛选数据;
  2. 再执行where,要知道筛选的条件,拿着条件去筛选;
  3. 最后拿着条件去指定表里面的指定列筛选

所以这里报错不认识这个total别名

mysql 复制代码
mysql> select name, total from exam_ret where chinese + math + english total<225;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'total<200' at line 1

上面这样也不行,因为对列做重命名,已经是最后一步了,将数据拿完,最后改一下名字

mysql 复制代码
mysql> select name, chinese+math+english total from exam_ret where chinese+math+english<225;

++查找语文成绩大于80且不姓张的同学:++

mysql 复制代码
mysql> select name,chinese from exam_ret where chinese>80 and name not like'张%';

++查找张某同学,其他的同学成绩必须>225且英语>80:++

mysql 复制代码
mysql> select name, chinese, math, english, chinese+math+english total from exam_ret where name like '张_' or (chinese+math+english>225 and english>80);
2.22 null的查询
mysql 复制代码
mysql> select * from t11 where name is null;
mysql> select * from t11 where name is not null;

null表示没有,' '表示有,但是是空串

2.3 结果排序

语法:

mysql 复制代码
select ... from table_name [where ...] order by column [asc|desc], [...]
#asc 为升序(默认为asc)
#desc 为降序

如果有nullnull视为比任何值都小

++语文成绩升序排序:++

mysql 复制代码
mysql> select name,chinese from exam_ret order by chinese;

++语文成绩升序、数学成绩降序、英语成绩降序:++

这个意思是,如果语文成绩一样,按数学降序排序;如果语文、数学成绩一样,按英语降序排序

mysql 复制代码
mysql> select name, chinese, math, english from exam_ret order by chinese asc, math desc, english desc;

++查询总分,降序排序++

mysql 复制代码
mysql> select name, chinese+math+english as total from exam_ret order by total desc;

为什么where后面无法使用别名,而这里可以使用:

在排序之前,是要先有合适的数据

  1. 先执行from,知道在哪个表
  2. 如果有where子句,再执行where,拿到筛选条件
  3. 筛出要的数据
  4. 筛选出的数据进行排序

order byname, chinese+math+english as total语句后面,所以order by后面可以跟别名

++查询姓张或者姓王的同学数学成绩,数学成绩降序:++

mysql 复制代码
mysql>  select name, math from exam_ret where name like '张%' or name like '王%' order by math desc;

2.4 筛选分页结果

mysql 复制代码
mysql> select * from exam_ret limit 5;	#从表的开始连续读取5行
mysql> select * from exam_ret limit 3,5;	#从指定位置(3, 下标从0开始)开始,连续读取5行

也可也这样使用,更加明确

mysql 复制代码
mysql> select * from exam_ret limit 4 offset 1;	#从1号下标开始, 连续读取4行


对未知的表进行查询,最后加上limit 1,防止数据过大,导致全表数据库卡死
只用在数据准备好了,才需要显示,limit的本质功能就是"显示",它的执行阶段会更加靠后

3. update

++修改指定同学成绩:++

mysql 复制代码
mysql> update exam_ret set english=100 where name='张炎炎';

++多列修改:++

mysql 复制代码
mysql> update exam_ret set english=21,math=100 where name='张焱焱';

++总分倒数前三的数学加上25分:++

mysql 复制代码
mysql> update exam_ret set math=math+30 order by chinese+math+english asc limit 3;

++所有同学数学成绩减10分:++

mysql 复制代码
mysql> update exam_ret set math=math-10;

当没有筛选条件的时候,要谨慎使用update,一个误操作,直接修改了全部的数据

4. delete

++删除指定同学的成绩:++

mysql 复制代码
mysql> delete from exam_ret where name='老八';

++删除整张表的数据:++

删除表结构和删除表的数据不一样!

mysql 复制代码
delete from t11;

这里删除整张表的数据,并不会将自动增量的值并不会清零 ,如果想将自动增量的值清零,可采用截断表

mysql 复制代码
mysql> truncate for_truncate;

deletetruncate区别:

  • delete会走事务,truncate不走事务,即truncate不会将操作痕迹记录在日志当中
    由于不走事务,所以truncate会比delete稍微快一点
  • truncate只能对整表操作
  • truncate会重置auto_increment

5. 插入查询结果

mysql 复制代码
mysql> create table duplicate_table (
    -> id int,
    -> name varchar(20)
    -> );
    
mysql> insert into duplicate_table values (2024,'aaa');
mysql> insert into duplicate_table values (2024,'aaa');
mysql> insert into duplicate_table values (2025,'bbb');
mysql> insert into duplicate_table values (2025,'bbb');
mysql> insert into duplicate_table values (2026,'ccc');

当表中有重复数据的时候,可采用:

mysql 复制代码
mysql> select distinct * from duplicate_table;

这样在显示的时候数据已经去重,可是并未影响到表中的数据

如果想得到没有重复数据的表,可以将该表的去重查询结果插入到另一个表当中,然后将原表重命名,最后将新表改为原始表的名字

mysql 复制代码
mysql> create table no_duplicate_table like duplicate_table;

插入查询结果:

mysql 复制代码
mysql> insert into no_duplicate_table select distinct * from duplicate_table;

重命名:

mysql 复制代码
mysql> rename table duplicate_table to old_duplicate_table,
    -> no_duplicate_table to duplicate_table;

为什么是rename方式进行:

将一个文件上传到Linux中,在上传的过程中一直在写入,这个过程并不是原子的,所以会上传到一个临时目录下,当然全部上传完毕之后,最后再统一将这个文件move到指定目录,move操作的原子的。

rename也是同理,等一切就绪了,然后统一放入、更新、生效等

6. 聚合函数

函数 说明
COUNT 返回匹配查询条件的行数。
SUM 返回匹配查询条件的列的总和。
AVG 返回匹配查询条件的列的平均值。
MAX 返回匹配查询条件的列的最大值。
MIN 返回匹配查询条件的列的最小值。

6.1 无分组聚合

示例还是采用之前的exam_ret

++统计总共有多少个学生:++

mysql 复制代码
mysql> select count(*) from exam_ret;

count(6)并不是指特定的列或条件,它只是一个值,mysql会将它解释为计算所有非NULL值为6的数量

++统计语文不同成绩个数:++

mysql 复制代码
mysql> select count(distinct chinese) from exam_ret;

count是对结果做聚合,就一个数字,所以要在聚合之前去重,再聚合

统计成绩总分:

mysql 复制代码
mysql> select sum(math) as math_ret from exam_ret;

统计平均分:

mysql 复制代码
mysql> select avg(english) as english_avg from exam_ret;

++统计不及格人数:++

mysql 复制代码
mysql> select count(math) as math_fail from exam_ret where math<60;

++最高分和最低分:++

mysql 复制代码
mysql> select min(chinese) ret from exam_ret;
mysql> select max(chinese) ret from exam_ret;

6.2 分组聚合

分组是对表当中的数据进行分组,然后根据分组再进行聚合统计

导入测试表(来自Oracle 9i):

mysql 复制代码
mysql> source /path/scott_data.sql;
  • dept部门表
  • emp员工表
  • salgrade工资等级表

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

mysql 复制代码
mysql> select deptno, max(sal) sal_max, avg(sal) sal_avg from emp group by deptno;

group by column,指定列名,实际分组是根据该列的不同行数据来进行分组的

分组条件deptno,组内一定相同,可以被聚合压缩

即分组就是把一张表按照条件在逻辑上拆成多个子表,然后对各自子表进行聚合统计

每个部门的每种岗位平均薪资和最低薪资:

mysql 复制代码
mysql> select deptno, job, avg(sal) sal_avg, min(sal) sal_min from emp group by deptno, job;

一般在group by当中出现的具体列名称才可以在select后面具体出现

还有一类就是聚合函数

++平均薪资低于2000的部门和它的平均薪资:++

  • 统计各部门平均工资:

    mysql 复制代码
    mysql> select deptno, avg(sal) sal_avg from emp group by deptno;
  • having配合group by使用,对结果进行过滤:

    mysql 复制代码
    mysql> select deptno, avg(sal) sal_avg from emp group by deptno having sal_avg<2000;

    havingwhere区别:

    • where是对具体的任意列进行条件筛选;
    • having对分组聚合之后的结果进行条件筛选

不是只有磁盘上的表结构导入到mysql,真实存在的表才叫表;中间筛选出来的、最终结果显示的,也是表,逻辑上的表,即可以理解为 mysql一切皆表

所以只要能处理好单表的crud,所有的sql场景都能够用统一的方式进行!

相关推荐
J.P.August2 分钟前
Oracle RAC 环境下数据文件误建在本地目录的处理过程
数据库·oracle
ThisIsClark2 分钟前
【后端面试总结】MySQL面试总结
mysql·面试·职场和发展
对酒当歌丶人生几何7 分钟前
Mybatis控制台打印SQL执行信息(执行方法、执行SQL、执行时间)
java·数据库·sql·mybatis
xiaoerbuyu123310 分钟前
ubuntu 连不上网 桌面 右上角没有网络图标 Ubuntu复制后虚拟网络失效问题
linux·运维·ubuntu
ThisIsClark11 分钟前
【后端面试总结】MySQL索引
mysql·面试·职场和发展
胖胖不胖、22 分钟前
解决:Openstack创建实例进入控制台报错Something went wrong, connection is closed
linux·服务器·openstack
楚疏笃1 小时前
linux安全管理-账号口令
linux·服务器·安全
LightOfNight1 小时前
Redis设计与实现第14章 -- 服务器 总结(命令执行器 serverCron函数 初始化)
服务器·数据库·redis·分布式·后端·缓存·中间件
沐多1 小时前
linux实时操作系统xenomai看门狗(watchdog)机制及作用介绍
linux·xenomai·实时linux
孤邑1 小时前
【Linux】网络通信
linux·服务器·网络·笔记·学习