MySQL学习-第一部分

文章目录

  • MySQL数据库
  • 1 概述
    • 1.1概述
    • 1.2安装MYSQL(Windows下)
      • 1.2.1需要注意的事项:
    • 1.3 Mysql的卸载
    • 1.4查看Mysql服务
    • 1.5启动/关闭SQL的服务
    • 1.6客户端登录/使用MySql
      • 登录
      • 退出
      • 问题:ERROR 1045 (28000)
        • 解决方案
          • 第一步:关闭Mysql服务
          • 第二步:跳过Mysql密码验证
          • 第三步:无密码方式进入Mysql
          • 第四步:将登陆密码设置为空
          • 第五步:更改自己的登陆密码
          • 最后一步:验证密码是否修改成功
    • 1.7常用的mysql命令
      • 登录mysql
      • 退出mysql
      • 查看数据库
      • 使用某个数据库
      • 创建数据库
      • 查看数据库中的表
      • 查看数据库版本号
      • 查看当前使用的数据库?
    • 1.8数据库中最基本的单元:表(table)
      • 1.8.1什么是表(table)?为什么使用table来存储数据?
    • 1.9 SQL语句的分类(重要)
    • 1.10 导入SQL文件
    • 1.11查看表内信息
    • 1.12 查看表结构
  • 2 SQL语句
    • 2.1 查询语句
      • 2.1.1 简单查询 select
      • 2.1.2 查询多个字段
      • 2.1.3 查询所有字段
      • 2.1.4 别名 as
      • 2.1.5 数学表达式+-/*
      • 2.1.6 select 后跟字符/数据
      • 2.1.7 **distinct** 去除重复记录
    • 2.2 条件查询
      • =
      • >= and <=
      • between and
      • is null
      • is not null
      • and
      • or
      • and 和 or 的优先级问题
      • in
      • not in
      • like
    • 2.3 排序 order by (asc/desc)
      • 单字段排序
      • 多字段排序
      • mysql order by 实现中文排序
      • 根据字段位置进行排序(不建议)
      • 综合案例
  • 3 数据处理函数
    • 3.1单行处理函数
      • lower
      • upper
      • substr
        • 例子:实现查询结果首字母大写
      • length
      • trim
      • str_to_date(必须严格按照标准输出)
      • data_format
      • format
      • round
      • rand
      • ifnull
      • case...when...then...else...end
      • TimestampDiff(时间差计算函数)
    • 3.2 分组函数(多行处理函数)
      • 注意事项(注意事项一定要写在开头)
      • count
      • max
      • min
      • avg
  • 4 分组查询(据说非常重要) group by
    • 4.1 什么是分组查询?
    • 4.2 执行顺序(非常重要)
    • 4.3 having
    • 4.4 实际的案例
    • 4.5 总结
  • 5 连接查询
    • 5.1 什么是连接查询?
    • 5.2 连接查询的分类?
    • 5.3 笛卡尔积现象
    • 5.4 给表起别名
    • 5.5 内连接 inner join
      • 5.5.1 等值连接
      • 5.5.2 非等值连接
      • 5.5.3 自连接
    • 5.6 外连接
      • 5.6.1 右外连接 right outer join
      • 5.6.2 左外连接 left outer join
      • 5.6.3 全连接
    • 5.7 连接两张表以上
  • 6 子查询
    • 6.1 什么是子查询?
    • 6.2 子查询可以出现在哪些位置?
    • 6.3 where子句中的子查询
    • 6.4 from子句中的子查询
    • 6.5 select 子句中的子查询
  • 7 union合并查询结果集
    • 7.1 什么是union?
    • 7.2 union如何使用?
    • 7.3 union使用时的注意事项
  • 8 limit (非常重要)
    • 8.1 limit是什么?
    • 8.2 limit的用法
    • 8.3 limit 的起始位置
    • 8.4 limit 的第二个参数
    • 8.5 分页的原理
  • 9 DQL的总结

MySQL数据库

1 概述

1.1概述

MySQL数据库

MySQL是一个**关系型数据库管理系统****,**由瑞典[MySQL AB](https://baike.baidu.com/item/MySQL AB/2620844) 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型和大型网站的开发都选择 MySQL 作为网站数据库。

(以上介绍来源于百度)

什么是数据库?什么是数据库管理系统?什么是SQL?它们之间的关系是什么?

数据库,全称为DataBase,简称DB按照一定格式存储数据的一些文件的组合。文件中存储了具有特定格式的数据。
数据库管理系统,全称为DataBaseManagementSystem,简称DBMS专门用来管理数据库中的数据的系统,可以对数据库中的数据进行增删改查等操作。常见的DBMS:MySQL,Oracle,MS SqlServer,DB2,sybase等
SQL,全称为Structure Query Language(结构化查询语言)程序员编写SQL语句,然后通过DBMS来执行SQL语句,最终完成对数据库中数据的操作SQL是一套标准,SQL能在大部分数据操作系统中都可以使用,如SQL,DB2,ORACLE等三者的关系:使用DBMS=》执行SQL=》操作DB

需要先安装MySql数据库管理系统,然后学习SQL语句的写法,然后使用DBMS,执行SQL,完成数据的操作。

DBAData Base Administrator 数据库管理员CRUD:(增删改查)
create		创建
retrieve	查询
update		更新
delete		删除

1.2安装MYSQL(Windows下)

1.2.1需要注意的事项:

端口号:端口号port是任何一个软件/应用都会有的,端口号是应用的唯一代表端口号通常和IP地址在一块,IP地址是用来定位计算机的,端口号port是用来定位某台计算机上的某个应用/服务的在同一台计算机上,端口号不能重复,具有唯一性Mysql数据库启动的时候,这个服务占用的默认端口是3306(可以在my.ini里面更改)字符集:设置MYSQL数据的字符集为UTF8服务名:最好不要更改,默认是mysql环境变量:将bin目录加入到环境变量path中设置管理员的密码:用户名默认root不能改,然后设置超级管理员的密码设置密码的同时,可以激活root账户远程访问激活远程访问:激活:root账户可以远程登录不激活:root账户只能在本机上使用

1.3 Mysql的卸载

【MySQL卸载方法】https://blog.csdn.net/qq_45776730/article/details/123258877

注意:每个版本可能不一致,按照个人需求和实际卸载


1.4查看Mysql服务

此电脑–>右键–>管理–>服务和应用程序–>服务–>mysql

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CNSmNYjb-1690357313819)(MySQL.assets/image-20220727160202370.png)]

mysql的服务默认是“自动启动”的状态,只有启动了mysql的服务,mysql才能使用。

可以右键更改启动方式


1.5启动/关闭SQL的服务

启动

net start mysql

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T6k3rWJa-1690357313824)(MySQL.assets/image-20220727163947608.png)]

注:start后面跟的是你配置的mysql服务的服务名称,若在之前更改了服务名称的,这里需要更改为对应的名称

如配置的服务名称为 mysql80 则应该是: net start mysql80

关闭

net stop mysql

1.6客户端登录/使用MySql

使用Mysql安装目录下bin目录下的mysql.exe打开,就可以进行登录

如果将mysql配置到了环境变量,就可以直接执行mysql命令

登录

mysql -u root -p 
回车
然后输入你的密码

退出

exit
或者
quit

问题:ERROR 1045 (28000)

Access denied for user ‘root’@‘localhost’ (using password: YES)

解决方案

【解决Mysql:ERROR 1045 (28000):Access denied for user ‘root‘@‘localhost‘ (using password: NO)的方法】https://www.jb51.net/article/250474.htm

以下命令行代码均在管理员权限下运行:

第一步:关闭Mysql服务
net stop mysql
第二步:跳过Mysql密码验证

注意:mysql8.0无法直接在my.ini中添加–skip-grant-tables来进行跳过密码验证,需要使用命令行的方式

mysqld -console --skip-grant-tables --shared-memory

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iue8BTkm-1690357313829)(MySQL.assets/image-20220727171008963.png)]

第三步:无密码方式进入Mysql

在上述步骤之后,再打开一个管理员模式运行的cmd.exe

不需要通过net start mysql打开mysql服务

然后输入

mysql -u root -p

直接回车,就可以进入mysql界面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tnDOHJ7i-1690357313834)(MySQL.assets/image-20220727171126037.png)]

第四步:将登陆密码设置为空
use mysql; (使用mysql数据表)
update user set authentication_string='' where user='root';(将密码置为空)
quit; (然后退出Mysql)
第五步:更改自己的登陆密码

1.关闭前两个cmd窗口(一定要关闭!);

2.在第三个窗口中输入代码;

然后输入

cd D:\mysql-8.0.19-winx64\bin  (此处输入自己电脑上的安装目录)
mysql -u root -p
(此处会显示输入密码,直接回车就好了,第四步我们已经将他置为空了)
ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';(By 后面跟的字符串就是你想要更新的密码)
最后一步:验证密码是否修改成功
quit(退出mysql)
mysql -u root -p 
(输入新密码,再次登录)

记录时间:2022-7-27-17:13 --好像是老问题了,之前一直没有改正过来,正好在复习的时候将其改正,一定要跟着步骤慢慢来。


1.7常用的mysql命令

注意:所有命令都需要用分号结尾(登录除外

​ 命令不区分大小写(也可以大小写混用)

​ 不见分号不执行

​ \c 指令用来终止

​ ctrl+c 退出MYSQL

登录mysql

mysql -u root -p 回车
输入密码

退出mysql

exit;

查看数据库

show databases;

使用某个数据库

use [数据库名称];

创建数据库

create database [数据库名称];
//然后查看数据库
show databases;

查看数据库中的表

show tables;

查看数据库版本号

select version()

查看当前使用的数据库?

select database();

1.8数据库中最基本的单元:表(table)

1.8.1什么是表(table)?为什么使用table来存储数据?

数据库中的表是以表格的方式来表示数据的

任何一张表都有行和列:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEIvR8pY-1690357313839)(MySQL.assets/image-20220727174653459.png)]

每行(row)称为一个记录(数据)。

每列(column)称为一个字段。

数据类型:字符串、数字、日期等。

约束:对每个字段进行约束,有不同的规则对每个字段唯一性等建立约束


1.9 SQL语句的分类(重要)

SQL语句有很多,根据功能和作用进行分类,更方便记忆和使用。

【数据库中DQL、DML、DDL、DCL、TCL概述】https://blog.csdn.net/weixin_44169484/article/details/119255935

DQL 数据查询语言Data Query Languageselect 查询DML 数据操作语言Data Manipulation Languageinsert 插入delete 删除(数据)update 更新DDL 数据定义语言Data Definition Languagecreate 创建drop 删除(表、数据库、约束、触发程序等)alter 修改Truncate语句:清空表里的数据。DCL 数据控制语言Data Control Languagegrant 给与权限revoke 回收权限TCL 事务控制语言Transaction Control Languagecommit 事务提交rollback 事务回滚Savepoint语句:为回退而存在,个数没有限制,与虚拟机中快照类似。savepoint是事务中的一点。用于取消部分事务,当结束事务时,会自动的删除该事务中所定义的所有保存点Set transaction语句:设置事务的各种状态,比如只读、读/写、隔离级别

1.10 导入SQL文件

xxx.sql这种文件被称为SQL脚本文件。
脚本文件中编写的是大量的SQL语句。
#我们执行SQL脚本文件时,其中的所有SQL语句都会被执行。
批量的执行SQL语句时,可以采用SQL脚本文件。
MySQL中执行脚本文件的方法:
在DOS窗口中输入
source + 脚本路径
或者是通过工具进行导入当需要导入大量的SQL数据的时候,可以使用导入SQL脚本的形式进行写入。

注意:

​ 路径中不能带有中文、空格

​ 注意观察文件内是否有关于创建数据库的语句,若没有,需要手动创建并选择数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b0ekhbBW-1690357313843)(MySQL.assets/image-20220729143806393.png)]

然后执行 source + SQL脚本文件路径 如下:

  • 注意,一定要是没有中文且没有空格的目录下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0ibRSMmM-1690357313848)(MySQL.assets/image-20220729143920722.png)]

1.11查看表内信息

导入成功之后,查看表:

show tables;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BgYaSKCQ-1690357313852)(MySQL.assets/image-20220729144134866.png)]

然后查看表内的数据:

select * from dept;   //查看dept表内的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFNjXGBL-1690357313857)(MySQL.assets/image-20220729144212701.png)]

select * from emp; //查看emp表中的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZrWYviZI-1690357313861)(MySQL.assets/image-20220729144307147.png)]

select * from salgrade; //查看salgrade表中的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v9QvbvVn-1690357313866)(MySQL.assets/image-20220729144359838.png)]

1.12 查看表结构

使用 desc + 表名;  //查询表的结构
分别是 字段名 类型 是否可以为空 主键约束 默认数值 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VXJ7LgB8-1690357313870)(MySQL.assets/image-20220729145451258.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Dx5h2zN-1690357313875)(MySQL.assets/image-20220729145515221.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UoOXKO2t-1690357313879)(MySQL.assets/image-20220729145524244.png)]

2 SQL语句

2.1 查询语句

2.1.1 简单查询 select

select 字段名 from 表名;

select 和 from 是关键字

字段名 和 表名 是标识符

对于大部分数据库管理软件来说SQL结构查询语言是通用的,所有的SQL语句都应该以“ ; ”分号结尾,且SQL语句不区分大小写(Windows系统下)。(Linux 系统默认是要区分的,需要在my.ini中加入lower_case_table_name=1可以设置为不区分大小写)

2.1.2 查询多个字段

使用逗号隔开

例如:查询deptno和dname两个字段

select deptno , dname from dept;

2.1.3 查询所有字段

第一种方式:把所有的字段写上

第二种方式:用*号代替所有字段(会把 “ * ”号转为字段名,效率低,可读性差,且无法按照自己想要的顺序进行排序

select * from dept;

2.1.4 别名 as

使用 原字段名 as 你想要更改成的名称(注意,若是中文字符,则需要使用单引号进行包裹)

注:只是将表头显示的列名改为对应的名称,原字段名不会发生改变,因为select语句只负责查询。

select deptno as '序号',dname as NAME from dept;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tzb9KHfC-1690357313884)(MySQL.assets/image-20220729174241425.png)]

可以省略 as 关键字,使用空格进行分割,MYSQL依然会将你后面那个名称作为别名,如:

select deptno '序号',dname NAME from dept;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RNLPupB2-1690357313889)(MySQL.assets/image-20220729174549719.png)]

假设起别名的时候,别名中有空格怎么办?

解决方法:

使用单引号进行包裹(双引号在部分数据库中不支持,如Oracle,但是在mysql中可以使用)

select deptno as 'maka 序号',dname 'baka 名称' from dept;

2.1.5 数学表达式±/*

可以使用数学表达式对数据进行计算

select ename, sal*12 as '年薪' from emp;
select ename, sal/12 as '年薪' from emp;
select ename, sal+12 as '年薪' from emp;
select ename, sal+12 as '年薪' from emp;

2.1.6 select 后跟字符/数据

使用select时,可以若select没有的字段时,就会报错

如:

mysql> select abc from emp;
ERROR 1054 (42S22): Unknown column 'abc' in 'field list'

但是若select 的目标是一个字符串,那么就会将这个字符串按照表记录的数量,打印对应数量的行,详细如下所示:

mysql> select 'abc' as '表中的abc' from emp;
+-----------+
| 表中的abc |
+-----------+
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
| abc       |
+-----------+
14 rows in set (0.00 sec)

同理,1000也被视为字符串

select 1000 as '表中的abc' from emp;

2.1.7 distinct 去除重复记录

把查询结果去除重复记录【distinct】
distinct只能出现在所有字段的最前方。
distinct出现在job,deptno两个字段之前,表示两个字段联合起来去重。

select distinct job from emp;
select distinct job,deptno from emp;//可以对分组函数使用distinct
select distinct round(avg(sal),2),job from emp group by job;select job , destinct deptno from emp;//错误

2.2 条件查询

查询符合条件的数据

select 字段名 from 表名 where 条件
= 等于
<> 或者 != 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
between ... and ... 两个值之间,等同于 >= and <=
is null 判断是否为空 (is not null)判断是否不为空
and 并且 
or 或者
in 包含 相当于多个 or (not in 不在这个范围中)
not 取非,主要用于 is 或者 in 中
like 模糊查询,使用各种通配符进行模糊匹配% 或者 _ 匹配% 匹配任意多个字符_ 下划线只匹配一个字符

例举:

查询薪资小于等于5000的所有员工的编号和名称

select empno as '编号', ename as '名称',sal as '薪资'  from emp where sal <= 5000;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BVRiVnjF-1690357313893)(MySQL.assets/image-20220729180724662.png)]

=

‘ = ’ 符号也可以使用在字符串对比上

比如查询姓名为‘smith’的所有信息

select * from emp where ename = 'smith';

>= and <=

查询大于2000小于6000的sal

select empno as '编号',ename as '名称',sal as '薪资' from emp where sal >= 2000 and sal <= 6000; 

或者

between and

select empno as '编号',ename as '名称',sal as '薪资' from emp where sal between 2000 and 6000;

is null

数据库中 null 不能使用 ‘ = ‘ 进行比对,需要使用 is null 进行比对

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资' from emp where comm is null;

is not null

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资' from emp where comm is not null;

and

用于两个条件语句的连接,意为 条件A和条件B 同时满足

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资' from emp where job = 'Manager' and sal > 2000;

or

用于两个条件语句的连接,意为 条件A和条件B 满足其中一个

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where job = 'Manager' or job = 'salesman';

and 和 or 的优先级问题

工资大于2500,且部门编号为10或者20的员工。

select * from emp where sal > 2500 and deptno = 10 or deptno = 20;

and 语句的优先级比 or 的优先级高不论位置

所以以上语句表示的是 工资大于2500和编号为10的 员工,或者编号为20的员工。

所以应该使用括号将低优先级的or进行包裹,让其优先级变高。

select * from emp where sal > 2500 and (deptno = 10 or deptno = 20);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8b2Tavv0-1690357313897)(MySQL.assets/image-20220730084233185.png)]

绿色为正确结果,红色为错误的结果。

in

包含,相当于多个 or

例如:查询工作岗位是Manager 和 salesMan 的员工:

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where job = 'Manager' or job = 'salesman';

用 in 的方式

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where job in ('Manager' , 'salesman');

注意:in 不是区间,是具体值,相当于job = ‘具体值’ or job = ‘具体值’;

not in

具体同上, 只不过是相反,不等于这几个值的意思。

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where job not in ('Manager' , 'salesman');

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pWa2t3gc-1690357313902)(MySQL.assets/image-20220730084902404.png)]

like

模糊查询

支持%或者_匹配

%匹配多个字符,_匹配一个字符

例如:

查询名字中含有 ‘ t ’ 的:

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where ename like '%t%';

名字中第二位是 ’ m ’ 的:

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where ename like '_m%';

若需要找 名字中带有下划线的:

使用 ’ \ ’ 转义字符,若名字中找带有 ‘ \ ’ 的:/ \

select empno '编号',ename '姓名',sal '薪资',comm '额外薪资',job '工作' from emp where ename like '\_%';

2.3 排序 order by (asc/desc)

排序总是在最后,如

select … from … where … order by

单字段排序

默认排序是升序,也就是默认带有order by [字段名] asc

select empno '编号',ename as '姓名',sal as '薪资' from emp order by sal (后面默认带一个asc表示为升序);

降序 desc

select empno '编号',ename as '姓名',sal as '薪资' from emp order by sal desc;

多字段排序

如:薪资升序的同时,名称按照A-Z的顺序排

使用 ’ , ’ 分隔不同的

select empno '编号',ename as '姓名',sal as '薪资' from emp order by sal asc , ename asc;

排序出来的结果,首先是按照第一个条件进行排序的,然后值相同的情况下,按照第二个条件进行排序。

mysql order by 实现中文排序

在mysql 中,我们经常会对一个字段进行排序,若不是中文字段则可以使用order by ColumnName,但进行中文字段排序,对汉字的排序结果往往都是错误的。 这是因为order by是根据对应字符的ASCII码排序。

如要实现按照中文拼音的排序,不想改变数据库结构的话,简单的做法是,在sql语句内加入CONVERT 函数即可。

select * from table order by CONVERT(列名 USING gbk);

https://blog.csdn.net/weixin_44948683/article/details/105842081

根据字段位置进行排序(不建议)

根据查询出来结果的第一个字段进行排序:(不建议,列顺序容易发送变化,且没有健壮性。)

select empno '编号',ename as '姓名',sal as '薪资' from emp order by 1 asc;

程序健壮性就是你的程序在遇到异常的情况下还能运行或者给予用户友好的提示。所以写代码的时候尽量考虑周全。

该做异常处理的就做异常处理,性能和正确性比起来一文不值。

综合案例

寻找工资在2000到3000之间,且job不为Manager,按照工资的大小降序排序,相同的薪资以名称升序排序。

select ename as '姓名',sal as '薪资' from emp where sal between 2000 and 3000 order by sal desc,ename asc;

3 数据处理函数

函数名作用
lower转换小写
upper转换大写
length取长度
substr取子串的长度
str_to_date字符串转为日期
date_format格式化日期
format设置千分位
round四舍五入
rand()生成随机数
ifnull可以将null转换成一个具体值

3.1单行处理函数

数据处理函数又被称为单行处理函数

单行处理函数的特点是:一个输入对应一个输出

和单行处理函数相对的是:多行处理函数(多个输入对应一个输出,例如统计所有员工的工资总和,select sum(sal) as ‘总薪资’ from emp;

lower

例如将显示的所有名称转为小写:

select lower(ename) as '姓名' from emp order by ename asc;

upper

将所有的字母转为大写

select upper(ename) as '姓名' from emp order by ename asc;

substr

方法体:substr(被截取的字符串, 起始下标, 截取的长度)

substr的起始下标从1开始

select substr(ename,1,2) as '截取之后的ename' from emp;

例子:找出员工名字第一个字母是A的员工信息?

第一种:模糊查询

select ename from emp where ename like 'A%';

第二种:substr方式

select ename from emp where substr(ename,1,1) = 'A';

例子:实现查询结果首字母大写

concat() 字符串的拼接

select concat(substr(upper(ename),1,1),lower(substr(ename,2,length(ename)))) as '首字母大写' from emp;

length

获取字符串的长度

select ename as '名称', length(ename) as '名称的长度' from emp;

trim

去除前后空白

例如 前端传过来的数据中前后带有空白,此时就需要使用trim

select ename from emp where ename = trim('   king  ');

但是中间的空格就不会去除

select ename from emp where ename = trim('   k i n g  ');
结果:Empty set (0.00 sec)

str_to_date(必须严格按照标准输出)

把字符串转为日期

 select * from emp where hiredate=str_to_date(1981-02-20);drop table if exists t_user;create table if not exists t_user(user_id int,user_name varchar(30),user_birth date);#插入数据时:insert into t_user values(1,'makabaka','1990-10-1'); #执行成功....Query OK, 1 row affected (0.01 sec)#但是如果插入时,没有按照对应的以 年-月-日 来插入,如下:insert into t_user values(1,'makabaka','10-1-1990'); #结果:ERROR 1292 (22007): Incorrect date value: '10-1-1990' for column 'user_birth' at row 1#执行错误,因为'19990-10-1'不是一个date类型的数据语法格式:str_to_date(日期的字符串,日期的格式)mysql 的日期格式:%Y	年%m	月%d	日%h	时%i	分%s	秒insert into t_user values(2,'wuxidixi',str_to_date('10-1-1990','%m-%d-%Y')); #此时:Query OK, 1 row affected (0.00 sec)#执行成功

str_to_date函数可以把字符串varchar转为日期date类型的数据

通常使用在insert into数据插入方面,因为某些字段会被定义为date类型的数据

需要通过该函数将字符串转为date类型

但是若插入时,字符串匹配了 [ 年-月- 日 ] 格式,就不用使用该函数。

了解一下:

#java中的日期格式
yyyy-HH-dd HH:mm:ss SSS

data_format

将date类型转换成一定格式的varchar类型字符串

用法:

date_format(日期类型的数据,需要显示的日期格式)
一般用在查询日期方面,设置展示的日期格式。select user_id as '编号',user_name as '姓名',date_format(user_birth,'%m/%d/%Y')  as '生日' from t_user;
#结果:
+------+----------+------------+
| 编号 | 姓名     | 生日       |
+------+----------+------------+
|    1 | makabaka | 10/01/1990 |
|    2 | wuxidixi | 10/01/1990 |
+------+----------+------------+
2 rows in set (0.00 sec)#select查询date型的数据时,会自动将date转为varchar类型显示在dos命令窗口中,并且采用磨人的mysql日期格式:'%Y-%m-%d'

format

数字的格式化,给数字添加千分位,第二个参数是保留的小数位数,且函数自带四舍五入

select ename as '员工名',format(sal,2) as '工资' from emp;
#结果:
+--------+----------+
| 员工名 | 工资     |
+--------+----------+
| SMITH  | 800.00   |
| ALLEN  | 1,600.00 |
...
| FORD   | 3,000.00 |
| MILLER | 1,300.00 |
+--------+----------+
14 rows in set (0.00 sec)
#当第二个参数为0时,表示取整
SELECT FORMAT(100.7654,3);//四舍   100.765
SELECT FORMAT(100.7655,3);//五入   100.766

round

四舍五入

round(数字, 需要保留的小数位数)

select round(1234.567,0) as 'result' from dept;
结果为:
+--------+
| result |
+--------+
|   1230 |
|   1230 |
|   1230 |
|   1230 |
+--------+
4 rows in set (0.01 sec)

第二个参数若为负数,则就往前四舍五入(以小数点的位置,负数为往前,往前进行四舍五入

如:

select round(1234.567,-1) as 'result' from dept;
结果为:
+--------+
| result |
+--------+
|   1230 |
|   1230 |
|   1230 |
|   1230 |
+--------+
4 rows in set (0.00 sec)

若数字为1235.666,此时再去取-1

mysql> select round(1235.666,-1) as 'result' from dept;
结果为:
+--------+
| result |
+--------+
|   1240 |
|   1240 |
|   1240 |
|   1240 |
+--------+
4 rows in set (0.00 sec)

可以看到,此时是按小数点的前一位,也就是10位作为四舍五入的位置。

rand

生成一个范围0-1的随机数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hwAma4Cr-1690357313907)(MySQL.assets/image-20220730180017319.png)]

生成100以内的随机数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GzkBehNQ-1690357313911)(MySQL.assets/image-20220730184244969.png)]

ifnull

空处理函数,专门处理空数据

在所有数据中,只要有null参与运算,则最终结果一定为null

如:计算年薪

select ename as '姓名', (sal + comm) * 12 as '年薪' from emp;
结果为:
+--------+----------+
| 姓名   | 年薪     |
+--------+----------+
| SMITH  |     NULL |
| ALLEN  | 22800.00 |
| WARD   | 21000.00 |
| JONES  |     NULL |
| MARTIN | 31800.00 |
| BLAKE  |     NULL |
| CLARK  |     NULL |
| SCOTT  |     NULL |
| KING   |     NULL |
| TURNER | 18000.00 |
| ADAMS  |     NULL |
| JAMES  |     NULL |
| FORD   |     NULL |
| MILLER |     NULL |
+--------+----------+
14 rows in set (0.00 sec)

为了避免这个现象,则需要使用ifnull函数。

用法:

ifnull(数据, 若为空时赋的值)

还是以上的例子,如果补助为null时,把补助设置为0

select ename as '姓名', (sal + ifnull(comm,0)) * 12 as '年薪' from emp;
结果为:
+--------+----------+
| 姓名   | 年薪     |
+--------+----------+
| SMITH  |  9600.00 |
| ALLEN  | 22800.00 |
| WARD   | 21000.00 |
| JONES  | 35700.00 |
| MARTIN | 31800.00 |
| BLAKE  | 34200.00 |
| CLARK  | 29400.00 |
| SCOTT  | 36000.00 |
| KING   | 60000.00 |
| TURNER | 18000.00 |
| ADAMS  | 13200.00 |
| JAMES  | 11400.00 |
| FORD   | 36000.00 |
| MILLER | 15600.00 |
+--------+----------+
14 rows in set (0.00 sec)

case…when…then…else…end

例子:当员工工作岗位为Manager的时候,工资上涨10%,当工作岗位为Salesman的时候,工资上调50%

select ename as '名称',job as '工作',sal as'薪资', (case job when 'Manager' then sal*1.1when 'salesman' then sal*1.5else sal end) as '真实薪资'
from emp where sal > 1000;

TimestampDiff(时间差计算函数)

TimestampDiff(间隔类型,前一个日期,后一个日期)TimestampDiff(YEAR,hiredate,now())间隔类型:second	秒minute	分钟hour	小时day		天week	星期month	月quarter	季度year	年

3.2 分组函数(多行处理函数)

多行处理函数的特点是,输入多行,最终输出一行

名称作用
count计数
sum求和
avg平均值
max最大值
min最小值

分组函数使用时,必须先进行分组(通过where或者其它语句筛选过后),才能使用。

若没有对数据进行分组,则整张表作为一个分组。

在分组函数后面使用where进行条件筛选的话,效率会变低

分组函数不能直接使用在where子句中

例子:

找出比最低工资高的员工信息

select ename as '姓名' ,sal as '薪资' from emp where sal > min(sal);
结果:
ERROR 1111 (HY000): Invalid use of group function :分组函数的使用无效
invalid:无效的    (valid:有效的)

所有的分组函数可以组合在一起使用

select sum(sal) as '工资总和',max(sal) as '最高工资',min(sal) as '最低工资',avg(sal) as '平均工资',count(*) as '数据总数' from emp; 结果:
+----------+----------+----------+-------------+----------+
| 工资总和 | 最高工资 | 最低工资 | 平均工资    | 数据总数 |
+----------+----------+----------+-------------+----------+
| 29025.00 |  5000.00 |   800.00 | 2073.214286 |       14 |
+----------+----------+----------+-------------+----------+

注意事项(注意事项一定要写在开头)

在comm中,有数据为null的话,分组函数会自动忽略null

例如,数据为

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HtYJ3xE6-1690357313916)(MySQL.assets/image-20220730192707185.png)]

当我们使用sum函数进行累加时:

因为其中有null,所以正常的运算符进行计算的话,则会返回null(因为null参加了运算,详情见上一章单行处理函数。

但是使用分组函数时,函数会自动忽略其中的null,不需要提前对null进行处理。

select sum(comm) as '补助总和' from emp;
结果:
+----------+
| 补助总和 |
+----------+
|  2200.00 |
+----------+
1 row in set (0.00 sec)

count

统计出符合条件的记录数

select count(ename) as 'emp表内的总数据数' from emp;

注意:count不会统计null的数量,会自动忽略null

select count(comm) as '补助总数' from emp;
结果为:
+----------+
| 补助总数 |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)

count(*) 和 count(具体字段)的区别:

count(*):查询所有的记录的数量,只要一条记录中有一个字段不为空,这条记录就是有效的,统计所有有效的字段。
count(具体字段):表示统计该字段下所有不为null的记录数量,当其中有为null的数据时,会跳过该记录。

max

找出数据中最大的一项。

例子:

找出最高工资?

select max(sal) as '最高工资' from emp;

min

找出数据中最小的一项

select min(sal) as '最低工资' from emp;

avg

取出所有数据的平均值

select avg(sal) as '平均工资' from emp;

4 分组查询(据说非常重要) group by

4.1 什么是分组查询?

在实际的应用中,可能需要对所有数据中的某一部分数据进行操作,这时候我们就要需要使用分组查询。

select ....
from ...
group by ...举例:计算每个部门的工资和?计算每个岗位的平均薪资?计算某个部门的最高薪资?

4.2 执行顺序(非常重要)

select ...
from ...
where ...
group by...
order by ...

以上是书写顺序

执行顺序:

1.from ...
2.where ...
3.group by ...
4.select ...
5.order by ...
select ename,sal from emp where sal > min(sal);
结果:
ERROR 1111 (HY000): Invalid use of group function
分组函数的无效使用

注意,此时的where在group by之前执行,也就是说,在分组之前会执行条件筛选,如此一来,按照正常逻辑写的数据查询,可能会出错,得到错误的结果。

为什么分组函数不能直接使用在where后面?

因为分组函数在使用的时候必须先进行分组,where执行的时候还没有分组,所以where后面不能出现分组函数。

select sum(sal) from emp;

这个没有分组,为啥sum()函数可以用呢?

因为 select 在 group by 之后执行 (按照如上的执行顺序) 。

4.3 having

having 是在group by分组之后,进一步对分组的数据进行筛选的关键字,不能脱离order by 单独使用,一定是紧跟在group by 后面的。

4.4 实际的案例

  1. 找出每个工作岗位的工资和?

思路:按照岗位分组,然后对每个分组进行求和

所以 group by job 然后会用到 sum() 函数

select job as '工作',sum(sal) as '岗位薪资'
from emp 
group by job;

分析:

执行顺序:从emp中查询数据,根据job字段进行分组,然后对每个分组执行sum()求和

思考:可以将ename加入select的条件吗?

可以,但是结果不符合需求或者输出错误的值

select ename,job,sum(sal) from emp group by job;

以上语句在mysql中可以执行,但是毫无意义,

以上语句在oracle中执行,会产生错误。

(说明mysql中的sql语法相对于oracle来说更加的松散)

结论:

​ 在一条select查询语句当中,若其中有group by语句,select 后面只能跟 参加分组的字段,以及分组的函数。

  1. 找出每个部门的最高薪资

思路:先按照每个部门的部门编号进行分组,然后使用max()分组函数进行取值。

select deptno as '部门编号', max(sal) as '部门最高薪资' from emp group by deptno;
结果为:
+----------+--------------+
| 部门编号 | 部门最高薪资 |
+----------+--------------+
|       20 |      3000.00 |
|       30 |      2850.00 |
|       10 |      5000.00 |
+----------+--------------+
3 rows in set (0.00 sec)
  1. 找出每个部门不同工作的最高薪资

思路:先按照每个部门进行分组,然后按照工作进行分组,最后使用max()

按照多个字段进行分组,不同字段之间用逗号隔开

select deptno as '部门编号',job as '工作',max(sal) as '最高工资' from emp group by deptno,job order by deptno;
结果:
+----------+-----------+----------+
| 部门编号 | 工作      | 最高工资 |
+----------+-----------+----------+
|       10 | CLERK     |  1300.00 |
|       10 | MANAGER   |  2450.00 |
|       10 | PRESIDENT |  5000.00 |
|       20 | ANALYST   |  3000.00 |
|       20 | CLERK     |  1100.00 |
|       20 | MANAGER   |  2975.00 |
|       30 | CLERK     |   950.00 |
|       30 | MANAGER   |  2850.00 |
|       30 | SALESMAN  |  1600.00 |
+----------+-----------+----------+
9 rows in set (0.00 sec)
  1. 找出每个部门最高的薪资,且只显示最高薪资大于3000的

思路:先按照每个部门进行分组,然后使用max函数显示最高的工资,然后通过having进行对分组后的数据进一步筛选。

select deptno as '部门编号',max(sal) as '最高工资' from emp group by deptno having max(sal)>3000;
执行结果:
+----------+----------+
| 部门编号 | 最高工资 |
+----------+----------+
|       10 |  5000.00 |
+----------+----------+
1 row in set (0.00 sec)

思考:以上的SQL语句的执行效率是否过低?

比较低,实际可以先将大于3000的数据找出来之后再进行分组。

参考:https://blog.csdn.net/weixin_34377065/article/details/94023858

select deptno as '部门编号',max(sal) as '最高工资' 
fromemp
wheresal>3000
group bydeptno;

优化策略:where和having 优先选择 where,where完成不了的,再选择having

  1. 找出每个部门的平均薪资,且只显示平均薪资高于2500的。

思路:按照每个部门进行分组,然后用avg()函数取平均值,然后筛选出2500以下的。

select deptno as '部门编号',round(avg(sal),1) as '最高工资' from emp group by deptno having avg(sal)>2500;

4.5 总结

单表查询章节结束

select ....
from ...
where ...
group by ...
having ...
order by ...执行顺序:
1.from
2.where
3.group by
4.having
5.select
6.order by

案例:

找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除去工作岗位为Manager的,且按照平均薪资进行降序排序。

思路:按照每个岗位进行分组,然后使用having去进行第二次平均薪资的筛选,然后使用not in manager 除去工作岗位为manager的,然后使用order by 平均薪资 desc 进行排序。

select job as '工作岗位',round(avg(sal),1) as '平均工资' 
fromemp
wherejob not in ('manager') // job != 'manager'也可以
group byjob
havingavg(sal)>1500
order byavg(sal) desc;+-----------+----------+
| 工作岗位  | 平均工资 |
+-----------+----------+
| PRESIDENT |     5000 |
| ANALYST   |     3000 |
+-----------+----------+
2 rows in set (0.00 sec)

5 连接查询

5.1 什么是连接查询?

从一张表中单独查询称为单表查询

多张表的数据,从A表中取出一部分,从B表中去除一部分,将这两部分连接起来,查询,称为连接查询。

5.2 连接查询的分类?

年份进行分类

SQL92:1992年出现的语法
SQL99:1999年出现的语法

连接方式分类

内连接等值连接非等值连接自连接
外连接左外连接(左连接右外连接(右连接
全连接

5.3 笛卡尔积现象

案例:查询每个员工所在部门的名称?

select ename,deptno from emp;
select denptno,dname from dept;select emp.ename as '员工姓名',emp.deptno as '部门编号',dept.dname as '部门名称'
from emp,dept; //没有任何条件限制
+----------+----------+------------+
| 员工姓名 | 部门编号 | 部门名称   |
+----------+----------+------------+
| SMITH    |       20 | OPERATIONS |
| SMITH    |       20 | SALES      |
| SMITH    |       20 | RESEARCH   |
| SMITH    |       20 | ACCOUNTING |
| ALLEN    |       30 | OPERATIONS |
| ALLEN    |       30 | SALES      |
| ALLEN    |       30 | RESEARCH   |
| ALLEN    |       30 | ACCOUNTING |
...
| MILLER   |       10 | OPERATIONS |
| MILLER   |       10 | SALES      |
| MILLER   |       10 | RESEARCH   |
| MILLER   |       10 | ACCOUNTING |
+----------+----------+------------+
56 rows in set (0.00 sec)//共有56条  笛卡尔积现象

当两张表进行连接查询,没有任何限制的时候,最终的结果是两张表记录的乘积,A表有5条,B表有6条,则结果就又5*6=30条。

这个现象叫做笛卡尔积现象。

得出结论:在进行表连接时,需要在连接时将条件增加到后面:

select emp.ename as '员工姓名',emp.deptno as '部门编号',dept.dname as '部门名称'
from emp,dept 
where dept.deptno=emp.deptno;//指定相同字段
结果:
+----------+----------+------------+
| 员工姓名 | 部门编号 | 部门名称   |
+----------+----------+------------+
| SMITH    |       20 | RESEARCH   |
| ALLEN    |       30 | SALES      |
| WARD     |       30 | SALES      |
| JONES    |       20 | RESEARCH   |
| MARTIN   |       30 | SALES      |
| BLAKE    |       30 | SALES      |
| CLARK    |       10 | ACCOUNTING |
| SCOTT    |       20 | RESEARCH   |
| KING     |       10 | ACCOUNTING |
| TURNER   |       30 | SALES      |
| ADAMS    |       20 | RESEARCH   |
| JAMES    |       30 | SALES      |
| FORD     |       20 | RESEARCH   |
| MILLER   |       10 | ACCOUNTING |
+----------+----------+------------+
14 rows in set (0.00 sec)  

最终的查询结果条数是14条,但是在匹配的过程中,匹配的次数还是没有减少,依然是56次,但是4选1。

就算加上条件也无法避免底层的匹配次数,底层还是会把表中的每一条行数据都给匹配一遍,只是显示的结果是有效数据

降低表的连接次数也是性能优化的重要手段

5.4 给表起别名

select e.ename as '员工姓名',e.deptno as '部门编号',d.dname as '部门名称'
from emp as e,dept as d
where e.deptno=d.deptno;//指定相同字段 SQL92语法

给表名起别名的话,使用as的话,好像会报错(未验证过

为什么select上可以直接使用from 的时候才定义的表别名呢?

因为执行顺序的不同(见上一章),首先执行的是from,后执行的select。

使用表名前缀可以提高执行效率。

如果使用了表的别名,则不能再使用表的真名。

性能影响可以忽略不计,但是您可以更好地阅读查询。这只是为了你的方便。

性能影响是在SQL Server程序本身中分配几kb的内存来存储别名等。与执行查询所需的其余操作相比,这几乎是小菜一碟。

5.5 内连接 inner join

5.5.1 等值连接

例:

查询每个员工所在的部门名称,并显示员工名称和部门名称

#SQL92语法select e.ename as '员工名',d.dname as '部门名'
fromemp e,dept d
wheree.deptno=d.deptno;
#92语法:结构不清晰,where后面容易混杂#SQL99语法
select e.ename as '员工名',d.dname as '部门名'
fromemp e
inner joindept d
one.deptno=d.deptno <-连接条件
wheree.ename='smith';#inner 可以省略 表示内连接,inner 可读性更好
#表连接和筛选语法进行了分离
#99语法后 on后面依然可以添加where来进行筛选

5.5.2 非等值连接

例子:

找出每个员工的薪资等级,要求显示员工名,薪资和薪资等级。

select e.ename as '员工名称',e.sal as '工资',s.grade as '工资等级'
fromemp e
inner joinsalgrade s 
one.sal between s.losal and hisal
order bye.sal asc;

5.5.3 自连接

例子:

查询员工的上级领导,要求显示员工名和对应的领导名称

selecte.empno as '员工编号',e.ename as '员工名',e.mgr as '领导编号',b.ename as '领导名称'
fromemp e
inner joinemp b
onifnull(e.mgr,7839) = b.empno;#ifnull替换空值为king的员工编号(自己是自己的领导),否则查询出来只有12条记录结果:
+----------+--------+----------+----------+
| 员工编号 | 员工名 | 领导编号 | 领导名称 |
+----------+--------+----------+----------+
|     7369 | SMITH  |     7902 | FORD     |
|     7499 | ALLEN  |     7698 | BLAKE    |
|     7521 | WARD   |     7698 | BLAKE    |
|     7566 | JONES  |     7839 | KING     |
|     7654 | MARTIN |     7698 | BLAKE    |
|     7698 | BLAKE  |     7839 | KING     |
|     7782 | CLARK  |     7839 | KING     |
|     7788 | SCOTT  |     7566 | JONES    |
|     7839 | KING   |     NULL | KING     |
|     7844 | TURNER |     7698 | BLAKE    |
|     7876 | ADAMS  |     7788 | SCOTT    |
|     7900 | JAMES  |     7698 | BLAKE    |
|     7902 | FORD   |     7566 | JONES    |
|     7934 | MILLER |     7782 | CLARK    |
+----------+--------+----------+----------+
14 rows in set (0.00 sec)

5.6 外连接

外连接的例子:

#内连接的特点:必须完全匹配的数据才能被查出来
select e.ename as '员工名',d.dname as '部门名'
fromemp e
inner joindept d
one.deptno=d.deptno;#外连接:把匹配不上的数据也依然显示出来
select e.ename as '员工名',d.dname as '部门名'
fromemp e
right joindept d
one.deptno=d.deptno;#外连接中,两张表是有主次关系的,需要指定主表,主表中的数据将会完全显示出来。
#内连接中两张表没有主次关系。#任何一个左连接都有一个右连接的写法
#任何一个右连接都有一个左连接的写法#外连接的查询结果条数 一定 大于等于 内连接的查询结果条数#outer关键字可以省略

5.6.1 右外连接 right outer join

#外连接:把匹配不上的数据也依然显示出来
#主要是为了将这张表的所有数据全都查询出来,捎带着关联查询左边的表
#就是为了将符合两个表条件的数据 和 右边表剩余的,没有匹配上的数据的全部显示出来
select e.ename as '员工名',d.dname as '部门名'
fromemp e
right outer joindept d
one.deptno=d.deptno;

5.6.2 左外连接 left outer join

select e.ename as '员工名',d.dname as '部门名'
fromemp e
left outer joindept d
one.deptno=d.deptno;

案例:

查询每个员工的上级领导,要求显示所有员工的名字和领导名

selecta.ename as '员工名称',b.ename as '领导名称'
fromemp a
left outer joinemp b
ona.mgr=b.empno;结果:
+----------+----------+
| 员工名称 | 领导名称 |
+----------+----------+
| SMITH    | FORD     |
| ALLEN    | BLAKE    |
| WARD     | BLAKE    |
| JONES    | KING     |
| MARTIN   | BLAKE    |
| BLAKE    | KING     |
| CLARK    | KING     |
| SCOTT    | JONES    |
=>| KING     | NULL     |<= king也被显示出来了
| TURNER   | BLAKE    |
| ADAMS    | SCOTT    |
| JAMES    | BLAKE    |
| FORD     | JONES    |
| MILLER   | CLARK    |
+----------+----------+
14 rows in set (0.00 sec)

5.6.3 全连接

全连接显示两侧表中所有满足检索条件的行。

只做一个了解,实际需求用的很少

了解一下写法就行了

#oracle 的全连接
select * from a full join b on a.id = b.id#mysql 的全连接
select * from a left join b on a.id = b.id
union
select * from a right join b on a.id = b.id

5.7 连接两张表以上

#若我们想要连接3、4、5张表怎么办?
select ...xxx
from ...a
(inner)join ...b
on ...a.x=b.y
left (outer) join ...c
on ...b.x=c.y
right (outer) join ...d
on ...c.x=d.y
group by ...
where ...
order by ...
#以此类推

案例:

找出每个员工的部门名称以及工资等级和上级领导,且要显示员工名、部门名、领导名、薪资、薪资等级

#各个表结构(只展示一部分):
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |mysql> select * from dept;
+--------+------------+----------+
| DEPTNO | DNAME      | LOC      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7369 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |

思路:三个表连接,然后显示对应的字段即可。

selecte.ename as '员工名称',d.dname as '部门名称',e2.ename as '领导名称',e.sal as '薪资',s.grade as '薪资等级'
fromemp e
inner joindept d
on e.deptno=d.deptno
inner join salgrade s
one.sal between s.losal and s.hisal
left outer joinemp e2
one.mgr=e2.empno;结果为:
+----------+------------+----------+---------+----------+
| 员工名称 | 部门名称   | 领导名称 | 薪资    | 薪资等级 |
+----------+------------+----------+---------+----------+
| SMITH    | RESEARCH   | FORD     |  800.00 |        1 |
| ALLEN    | SALES      | BLAKE    | 1600.00 |        3 |
| WARD     | SALES      | BLAKE    | 1250.00 |        2 |
| JONES    | RESEARCH   | KING     | 2975.00 |        4 |
| MARTIN   | SALES      | BLAKE    | 1250.00 |        2 |
| BLAKE    | SALES      | KING     | 2850.00 |        4 |
| CLARK    | ACCOUNTING | KING     | 2450.00 |        4 |
| SCOTT    | RESEARCH   | JONES    | 3000.00 |        4 |
| KING     | ACCOUNTING | NULL     | 5000.00 |        5 | <=左外连接显示了领导编号为null| TURNER   | SALES      | BLAKE    | 1500.00 |        3 |
| ADAMS    | RESEARCH   | SCOTT    | 1100.00 |        1 |
| JAMES    | SALES      | BLAKE    |  950.00 |        1 |
| FORD     | RESEARCH   | JONES    | 3000.00 |        4 |
| MILLER   | ACCOUNTING | CLARK    | 1300.00 |        2 |
+----------+------------+----------+---------+----------+
14 rows in set (0.00 sec)

6 子查询

6.1 什么是子查询?

select 中嵌套 select 查询语句,被嵌套的 select 语句称为子查询。

6.2 子查询可以出现在哪些位置?

select ..(select)
from..(select)
where..(select)#综上,select可以出现在select\from\where语句的后面

6.3 where子句中的子查询

案例:找出比最低工资高的员工姓名和工资

select ename,sal
from emp
where sal > (select min(sal) from emp);#程序会首先执行子查询 select min(sal) from emp; 得到最低的工资
#然后就根据查询到的最低工资与sal对比,然后返回所有满足条件的记录

6.4 from子句中的子查询

from后面的子查询,可以将子查询的查询结果当做一张临时表(技巧)

案例:

​ 找出每个岗位的平均工资的工资等级(按照岗位分组,求平均值,再进行分等级)

#首先按照岗位来分组,算出平均工资
select job,round(avg(sal),0) from emp group by job;
#然后算出来的表如下:
+-----------+-------------------+
| job       | round(avg(sal),0) |
+-----------+-------------------+
| CLERK     |              1038 |
| SALESMAN  |              1400 |
| MANAGER   |              2758 |
| ANALYST   |              3000 |
| PRESIDENT |              5000 |
+-----------+-------------------+
5 rows in set (0.00 sec)#然后把这个表跟salgrade进行连接
select temp.job as '工作岗位',temp.avgsal as '岗位平均工资',s.grade as '薪资等级'
from(select job,round(avg(sal),0) as avgsal from emp group by job) temp
inner joinsalgrade s
ontemp.avgsal between s.losal and s.hisal;

一定要有嵌套的思想,和明确的思路,每个表查出来是什么要有一个大概的认识。

6.5 select 子句中的子查询

找出每个员工的部门名称,要求显示员工名和部门名

select e.ename,d.dname,d.dname
from emp e
join dept d
on e.deptno=d.deptno
order by e.ename;
#select 子句 有且只能有返回一条数据
select e.ename as '员工名',(select d.dname from dept d where e.deptno=d.deptno) as '部门名称' from emp e order by e.ename;

select子查询在select之后时,子查询只能每次查询返回一条结果。

7 union合并查询结果集

7.1 什么是union?

“UNION表示“并”,当用的时候,系统会自动将重复的元组去掉,如果要保留重复元组则就用UNION ALL UNION 会合并重复数据,(由于要合并重复,该操所 隐藏着一个 排序的操作.)UNION ALL 简单合并,不会合并重复的. SQL中union运算操作的理解 在SQL中,对于并运算,可以使用union关键字.”

#union 的效率会高一些 对于表连接来说
#每连接一次表,匹配次数满足笛卡尔积
#但是union可以减少匹配的次数,在减少匹配次数的情况下,可以完成两个结果集的合并、拼接
# a表连接b表
# a、b、c三个表各有10条数据,则连接需要(笛卡尔积)10*10*10=1000次
# 使用union连接三个表:a连接b:10*10=100  a连接c:10*10=100 总需:100+100=200次
# 1000>200次

7.2 union如何使用?

select ename,job from emp where job="manager"
union
select ename,job from emp where job="salesman"

7.3 union使用时的注意事项

select ename,job from emp where job="manager"
union
select ename from emp where job="salesman"
==>
ERROR 1222 (21000): The used SELECT statements have a different number of columns
#以上语句是错误的,因为union在合并结果集的时候,要求两个查询的结果必须列数相同select ename,job from emp where job="manager"
union
select ename,sal from emp where job="salesman"
==>
+--------+---------+
| ename  | job     |
+--------+---------+
| JONES  | MANAGER |
| BLAKE  | MANAGER |
| CLARK  | MANAGER |
| ALLEN  | 1600    |
| WARD   | 1250    |
| MARTIN | 1250    |
| TURNER | 1500    |
+--------+---------+
7 rows in set (0.01 sec)
#以上语句在mysql中可以执行,但是在oracle中会报错,因为oracle语法更加严格。

8 limit (非常重要)

8.1 limit是什么?

limit 是将查询结果集的一部分显示出来,通常使用在分页查询之中。

分页是为了提高用户的体验。

8.2 limit的用法

limit 跟在语句最后面

limit 有两个参数,一个是其实的下标,第二个是要取的长度

当limit 后面只跟一个参数时,默认是将要取的长度。

注意:起始下标从0开始,且在mysql中,limit在order by之后执行

selectename,sal
fromemp
order bysal desc
limit 0,5;+-------+---------+
| ename | sal     |
+-------+---------+
| KING  | 5000.00 |
| SCOTT | 3000.00 |
| FORD  | 3000.00 |
| JONES | 2975.00 |
| BLAKE | 2850.00 |
+-------+---------+
5 rows in set (0.00 sec)#在mysql中,limit在order by之后执行

在mysql中,limit在order by之后执行

8.3 limit 的起始位置

# limit的起始位置跟数组的起始位置是一样的
如:
arr[]={1,2,3,4,5,6,7,8,9}
limit 5,2 取出的将会是{6,7}
下标默认是从0开始的
limit 0,2 取出的是 {1,2}
limit 1,2 取出的是 {2,3}

8.4 limit 的第二个参数

案例:

取出工资排名是在【5-9】名的员工

#
select ename as '员工名称',sal as '工资'
from emp 
order by sal desc
limit 4,5;
#第一个参数是从第5名开始的,由于下标是从0开始,所以第一个参数是5-1=4
#注意:是第5到9名员工,实际上是 [5,6,7,8,9]  结果中是包含了5的
#所以第二个参数是 (9-5)+1=5条记录

8.5 分页的原理

#需求:需要我们每页显示3条数据
#先确定第二条数据,第二条数据是页面大小,也就是返回的数据条数,所以是3 固定不变第一页: limit 0,3  [0,1,2]
第二页: limit 3,3	[3,4,5]
第三页: limit 6,3	[6,7,8]
第四页: limit 9,3	[9,10,11]
....

指定页面大小为pageSize

指定当前页码为pageNum

那么可以得出

第pageNum页: limit pageSize(pageNum-1),pageSize*

//模拟后台管理的分页   
@Controller
public static void main(String[] args){int pageNo=5;int pageSize=10;int startIndex = (pageN0 -1 ) * pageSize;String sql="select ename from emp order by ename desc limit"+startIndex+','+pageSize+";"//...然后使用SQL
}

9 DQL的总结

select...
from...
where...
group by...
having...
order by...
limit...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/8365.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Clion开发STM32之W5500系列(综合实验)

说明 此为w5500模块的综合实验测试模块,包含dhcp、dns、ntp以上三个模块的驱动参考之前的文章&#xff0c;本篇不做说明.使用的开发芯片 stm32f103vet6系列,外设接口使用的spi2 实验内容: 通过dhcp动态获取ip,通过dns解析NTP服务域名的ip通过NTP服务ip获取时间 w5500配置驱…

学生护眼台灯几瓦最舒适?2023全新五款护眼台灯推荐

每次经过学校&#xff0c;发现戴眼镜的小学生真的不少&#xff0c;通过近几年的儿童以及青少年的近视人数可看出&#xff0c;我国的近视人数中&#xff0c;儿童以及青少年占比53.5%&#xff0c;所以许多家长逐渐重视孩子用眼健康问题&#xff0c;会选择护眼台灯用于孩子写作业和…

第1章 获取数据库中的数据

CoreShop源程序是以数据库优先进行定义的&#xff0c;所以其本身不包含代码优先的定义&#xff0c;但本从更习惯于代码优先&#xff0c;所以为其定义了代码优先的定义。 1 CoreCms.Net.Model.Entities.SysRole using SqlSugar; using System.ComponentModel.DataAnnotations…

【JavaEE初阶】Tomcat安装与使用及初识Servlet

文章目录 1. Tomcat的安装与使用1.1 Tomcat安装1.2 Tomcat的启动1.3 Tomcat部署前端页面 2. Servlet2.1 Servlet是什么2.2 第一个Servlet程序2.3 常见错误 1. Tomcat的安装与使用 1.1 Tomcat安装 在浏览器中搜索Tomcat,打开官方网页.Tomcat官网 点击下载Tomcat8. 点击下载压…

PSP - 使用 MMseqs2 工具快速搜索蛋白质序列数据库 (GMGC)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131934642 MMseq2 是非常强大和高效的生物信息学软件&#xff0c;可以在极短的时间内对大规模的核苷酸和蛋白质序列进行搜索和聚类。主要特点有&a…

fpga_pwm呼吸灯(EP4CE6F17C8)

文章目录 一、呼吸灯二、代码实现三、引脚分配 一、呼吸灯 呼吸灯是指灯光在微电脑的控制之下完成由亮到暗的逐渐变化&#xff0c;使用开发板上的四个led灯实现1s间隔的呼吸灯。 二、代码实现 c module pwm_led( input clk ,input rst_n ,output reg [3:0] led ); …

spring学习笔记六

一、构造器注入 1.1、BookDao接口和实现类 public interface BookDao {void save(); } public class BookDaoImpl implements BookDao {private int connectionNum;private String databaseName;public BookDaoImpl(int connectionNum, String databaseName) {this.connectio…

【Spring MVC】小文件下载的多种方法

文章目录 HTTP Header 之 Content-Disposition文件下载代码Servlet 实现方式 1Servlet 实现方式 2Spring 实现方式 1 Content-Disposition 指定 inline Win、JDK 17、 Spring Boot 3.1.2 HTTP Header 之 Content-Disposition 以下内容来自 mdn web docs 在常规的 HTTP 应答中&…

c++网络编程:Boost.asio源码剖析

1、前言 Boost库是一个可移植、提供源代码的C库&#xff0c;作为标准库的后备&#xff0c;是C标准化进程的开发引擎之一。Boost库由C标准委员会库工作组成员发起&#xff0c;其中有些内容有望成为下一代C标准库内容。在C社区中影响甚大&#xff0c;是不折不扣的“准”标准库。…

未来行星探索希望:新型多脚机器人-团队版

机器人正在探索一个模拟的外星环境 即使一个机器人失败了&#xff0c;其余的团队成员也可以抵消它的损失。 背景 虽然探测器取得了令人难以置信的发现&#xff0c;但它们的轮子可能会拖慢它们的速度&#xff0c;而不稳定的地形可能会导致损坏。虽然没有东西可以取代“毅力号”…

Vue3输入框(Input)

APIs 参数说明类型默认值必传width输入框宽度string | number‘100%’falseaddonBefore设置前置标签string | slot‘’falseaddonAfter设置后置标签string | slot‘’falseallowClear可以点击清除图标删除内容booleanfalsefalsepassword是否启用密码框booleanfalsefalsedisabl…

tomcat调优2-具体实现

您好,可以通过修改Tomcat的配置文件来实现上述的Tomcat调优措施。 更改JVM内存配置 在Catalina服务的启动脚本catalina.sh中找到JAVA_OPTS变量,增加Java堆空间参数: JAVA_OPTS“-Xms512m -Xmx4096m” 调整线程池参数 在server.xml中的Connector标签中添加executor属性: &…

两个小封装电机驱动芯片:MLX813XX、A4950

一&#xff0e;MLX813XX MELEXIS的微型电机驱动MLX813XX系列芯片集成MCU、预驱动以及功率模块等能够满足10W以下的电机驱动。 相对于普通分离器件的解决方案&#xff0c;MLX813XX系列电机驱动芯片是一款高集成度的驱动控制芯片&#xff0c;可以满足汽车系统高品质和低成本的要…

Spring Boot实践一

一、Spring Boot简介 Spring Boot是一个基于Spring框架的快速开发应用程序的工具。它提供了一种快速、方便的方式来创建基于Spring的应用程序&#xff0c;而无需繁琐的配置。Spring Boot通过自动配置和约定大于配置的方式&#xff0c;使得开发者可以更加专注于业务逻辑的实现&…

【CEEMDAN-WOA-LSTM】完备集合经验模态分解-鲸鱼优化-长短时记忆神经网络研究(Python代码实现)

目录 &#x1f4a5;1 概述 1.1 完备集合经验模态分解原理 1.2 鲸鱼优化 1.3 LSTM &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Python代码实现 &#x1f4a5;1 概述 1.1 完备集合经验模态分解原理 早期的 EMD 方法具有较强的自适应性&#xff0c;能够有…

【node.js】03-http模块

目录 一、什么是http模块 二、创建基本的WEB服务器 三、req请求对象 四、res响应对象 五、根据不同的url响应不同的JSON内容 一、什么是http模块 http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的 http.createServer() 方法&#xff0c;…

Etcd 节点为啥不能设置偶数

在etcd集群中&#xff0c;最好不要设置偶数数量的节点。这是因为etcd使用Raft一致性算法来确保数据的一致性和高可用性。Raft算法要求在进行Leader选举和数据复制时&#xff0c;节点数必须是奇数个&#xff0c;以保证算法的正确性和容错性。 主要原因如下&#xff1a; Leader选…

深度学习推理和训练

优化和泛化 深度学习的根本问题是优化和泛化之间的对立。 • 优化&#xff08;optimization&#xff09;是指调节模型以在 训练数据 上得到最佳性能&#xff08;即机器学习中的学习&#xff09;。 • 泛化&#xff08;generalization&#xff09;是指训练好的模型在 前所未…

软考高级科目怎么选?这份秘籍请收好!

2023年软考下半年报名即将开启&#xff0c;软考高级含金量比较高&#xff0c;每年很多人报名&#xff0c;要考软考高级&#xff0c;选哪个科目比较好是每年大家关心的&#xff0c;2023年软考高级选哪个科目还得结合自身所学和工作所需去选择。看工作岗位的需求&#xff0c;工作…

Java的0xFFFF在赋值、比较时引起的困惑

Java中的0xFFFF是整型&#xff0c;在赋值、比较的时候容易引起混淆&#xff0c;涉及到符号位、数值大小&#xff0c;赋值给什么类型的变量。我今天在编码的时候就遇到了一些困惑。用代码样例的形式记录下来&#xff0c;加深理解&#xff1a; package com.thb;public class Tes…