MySQL数据库操作篇4(内置函数&连接查询&子查询)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL数据库操作篇4(内置函数&连接查询&子查询)

MySQL除了提供一些聚合函数供我们使用,同时还提供了很多的内置扩展函数,这些函数有的是进行日期处理的,有的是进行字符串处理的,有的则是进行数值处理,以及其它的种种函数,这些函数可以帮助我们对数据进行加工,得出我们想要的信息,需要注意的是函数要在查询语句select中使用,不可单独使用

目前为止,我们接触的查询函数,都是针对一张单表,但是很多的数据是彼此关联的,关系模型如此受欢迎,也是因为它较好的解决了多张表互相联系的查询,这篇文章开始,我们就正式开始了复合查询的学习,学习不同表中的数据如何进行关联

子查询是指在一个语句中,出现多个嵌套的select查询语句

在本篇文章中,将会用到4张表,部门表(dept),员工表(emp),信息表(msg),薪水等级表(salgrade),表中具体定义就不给出了,将在例子中体现出来


内置函数

1.日期函数

日期函数能方便对数据库中的日期数据进行处理,具体函数及功能描述如下表

image.png

注意日期和时间并不是一个东西,日期是指年月日,而时间是指时分秒

加下来依次举例这些日期函数的用法,看下图

上面这几个函数是比较简单的,看一眼基本就知道该怎么使用了,其中时间戳是指从指 Unix 时间戳,即自从 Unix 纪元(1970 年 1 月 1 日 00:00:00)到当前时间的秒数,这里数据库将其转换成日期和时间的形式显示出来

注意date函数中的参数不一定是now(),你可以参数其他的日期时间,最后都会截取日期部分

接下来我们看一下稍微有些麻烦的函数,它们是如何操作的

先看看date_add()的用法,这个是往一个给定的日期中增加某个日期单位的数目,然后返回增加后的日期,例如给定一个日期为'2023-7-10',给这个日期加上6天,返回6天后的日期

具体操作语句如下:

select date_add('2023-7-10', interval 6 day);

date_sub()的用法,这个是往一个给定的日期中减去某个日期单位的数目,然后返回减去后的日期,例如给定一个日期为'2023-7-10',给这个日期减去15天,返回15天前的日期

具体操作语句如下:

select date_sub('2023-7-10', interval 15 day);

 

datediff()这个函数需要给定两个日期参数,然后该函数会返回这两个日期之间的天数差值

假设计算'2023-06-25' 与 '2023-7-10'之间相差了多少天,就可以使用datediff()来解决

具体操作如下

select datediff('2023-7-10', '2023-06-25');

2.字符串函数

字符串函数能方便对数据库中的字符串数据进行处理,具体函数及功能描述如下表

image.png

字符串函数有很多,但是很多函数看看就知道怎么使用了,因此,这样的函数就不再演示了,笔者将稍微有些复杂的挑出来演示

concat()这个函数可以将多个字符串拼接起来,以员工表来演示

显示员工的一些信息,格式为:xxx的职业是xx, 工资为xx

select concat(ename, ',职业是', job, ',工资为', sal) from emp;  

replace(str,  search_str,  replace_str),该函数可以用来替换一个字符串中的某些内容

substring()这个函数可以看作是left函数的进阶版,可以从指定位置x处取n个字符

下图程序演示从第3个字符开始取5个字符

ltrim(),该函数用来删除字符串左侧的空格,rtrim()是删除字符串右侧的空格

下面演示该函数的用法,要注意该函数不会修改原始数据,而是返回一个新的字符串

  

3. 数学函数

数学函数能方便对数据库中的数值数据进行处理,具体函数及功能描述如下表

image.png

数学函数,abs(), bin(), hex(), conv(),ceiling(), floor()这些是比较简单的函数,我们演示一下如何使用即可,剩下几个我们详细看看如何使用


  • num:要进行转换的数值
  • from_base:原始数值的数制,可以是2到36之间的任意整数
  • to_base:目标数值的数制,可以是2到36之间的任意整数

format()是用来保留小数的位数(会自动进行四舍五入)

rand()产生从0.0到1.0之间的任意一个数,如果想要产生0-100之间的随机数,那么将rand()*100并将结果进行取整即可

mod()函数,第一个参数是要被取模的数,第二个参数是用哪个数来取模

4.其它的函数

除了对数据进行处理的相关函数,MySQL还提供了一些其他的,查询用户信息的相关函数,这些函数不是很多,也并不常用,大家简单了解一下

image.png

user(), database(), ifnull(val1, val2)的使用相对比较简单,这里简单演示一下

md5()以及password()是对密码进行处理的相关函数,我们来详细了解一下这两个函数的用途。数据库在保存数据的时候,难免要存储用户的密码信息,如果用户的密码信息直接就存放到库中,这是很危险的一个举动,如果数据库的信息被别人盗取,或者被一些不法分子利用管理权限窃取,因为密码是明文存放的,所以在数据中找到某个用户就能直接得出他的密码。为了杜绝这样的事情发生,在存储密码数据的时候,数据库通常不会明文存放密码,而是将用户的密码通过某种规则,进行加密,将加密之后形成的字符串存储到数据库中,这样即使不法分子窃取了数据库数据,也不知道用户的真实密码是什么

而md5()就是对用户密码进行加密的一个函数,把用户的密码作为参数传进去,会返回一个32位字符串,就是加密过后的密码

我们建立一个简单的用户表来演示md5()的使用,表的定义如下

create table user(

user_name varchar(30),

password varchar(32)

);

如果直接插入,那么就会造成密码明文显示,密码就有很大的风险

通过md5()的使用,就可以对密码进行加密,那么如何将密码进行匹配呢?

通过查找实例可知,想要进行密码匹配就要再次使用md5()函数,并且提供正确的密码,然后才能查找到该用户,password()的用法是类似的,区别是password的加密更加复杂,需要更多的空间来存储,这里就不演示了


复合查询

笛卡尔积

首先我们得明白为什么会用到复合查询,然后明白复合查询是基于什么原理实现的,最后了解复合查询如何使用,接下来我们用职工表来说明

上图是部门表和员工表的所有信息,就拿员工表和部门表来说,在员工表中可以查到该员工所属部门的部门号,但是并没有部门的名称,现在要求查询员工的所有信息以及该员工所属部门的部门名称,这该怎么办,部门名称在部门表中,如果我们想要做到既有员工信息又有部门信息,那么就要将两张表统合在一起

那么如何将两张表统合在一起呢,计算机不想我们人那么灵活,可以直接分析,手动将两张表汇成一张表,那么计算机中采用的方法就是将两张表做笛卡尔积

什么是做笛卡尔积,简单来说就是将表A中的每一行与表B中的所有行都进行一个连接组成一系列新的信息,如下图

如上表,查找每位同学的班主任是谁,可以将表A与表B做笛卡尔积,但是可以明显发现,笛卡尔的结果虽然做到了将两张表的信息统合在一起,但是有很多的信息我们是不需要的,比如上表,小王的班级是a,和表B中的班级b的连接就显得没有意义,所以我们往往会对笛卡尔的结果进行一次筛选,而这个筛选的媒介就是两张表中的共同属性,也就是外键,如果两张表中的共同属性的值相同,则这个信息就保留,否则都剔除,也就是A.班级 = B.班级,班级符合,可以找到自己的班主任,如果A.班级 != B.班级,班级都不匹配,那么B.班级的班主任就不是该同学的班主任,这样的信息应该剔除掉,筛选后我们就能得到自己想要的信息了,这里举例是两张表,笛卡尔积可以多张表同时进行


根据上述笛卡尔积的原理,我们接下来实现在数据库中查找员工所有的信息以及所在的部门名,MySQL中要进行多表连接(即做笛卡尔积),只需要在select的from子句中把要用到的表列出来即可,如下图,将员工表和部门表进行连接(数据太多,未显示完全)

同样,这样做有很多的信息都是没用的,所以我们要进行一次筛选,也就是用部门号筛选

select * from emp, dept where emp.deptno = dept.deptno;

查询结果如下

自连接

进行复合查询的时候,如果一张表自己和自己连接,那么这样的连接过程称为自连接,因为自连接的表名都是一样的,因此要给参与连接的表取个新的不重复的名字,这样能够标明出不同的表,方便条件筛选

例如:将部门表与部门表进行自连接

select * from dept as A, dept as B where A.deptno = B.deptno;

什么情况下会用到自连接呢,举个例子,我们需要查找WARD这个人的上级领导,因为他的上级领导也是员工,也在员工表中,想要查找他的上级领导是哪个人,就要在mgr这一列得到WARD这个人的上级领导的员工号,从而找到这个领导

select leader.empno,leader.ename from emp leader, emp worker where leader.empno = worker.mgr and worker.ename='WARD';

内连接

内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,笔者前面所述的查询都是内连接,也是在开发过程中使用的最多的连接查询

前面我们在进行内连接的时候,直接在from子句中写出要连接的表,当然内连接还有一种比较标准的写法,接下来看看这个比较标准的写法

select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件;

-- 用前面的写法

select ename, dname from emp, dept where emp.deptno=dept.deptno and

ename='SMITH';

-- 用标准的内连接写法

select ename, dname from emp inner join dept on emp.deptno=dept.deptno and

ename='SMITH';  

外连接

左外连接:如果联合查询,左侧的表完全显示我们就说是左外连接

语法形式:select 字段 from 表名1 right join 表名2 on 连接条件;

右外连接:如果联合查询,右侧的表完全显示我们就说是右外连接

语法形式:select 字段 from 表名1 right join 表名2 on 连接条件;

接下来建立两张表来演示这个过程

create table stu (id int, name varchar(30)); -- 学生表

insert into stu values(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');

create table exam (id int, grade int); -- 成绩表

insert into exam values(1, 56),(2,76),(11, 8);

要求:查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来

按照连接的标准写法,也就是用join 和 on这种形式,如果两个表中在on的条件下没有匹配项,那么就不会显示出来,这和题目要求的学生没有成绩,也要将学生的信息显示出来相违背,因此需要使用左外连接,使用左外连接后,在左边的表中的信息即使没有与右表相匹配的项,也能够显示出来,这就保证了左表数据的完整性

我们用内连接和左外连接的形式分别求一下,对比结果是否如此

因为右外连接就是与左外连接相反,这里就不再演示了,用法都是类似的


子查询

有些需要查询的内容,仅用一个查询语句是无法完成任务的,需要多层嵌套查询才能完成任务,像这样嵌入在其他sql语句中的select语句,就称为子查询,也叫嵌套查询

单行子查询

子查询的结果只返回一行的,我们称之为单行子查询,怎么理解呢?我们举个例子,查找和WARD处于同一个部门的所有员工的信息,查询语句如下

select * from emp where deptno = (select deptno from emp where ename='WARD');

在这个查询语句中,括号里的这个子查询,指明了查询WARD,所以查询结果只有一行,也就是提供给主查询语句的数据只有一行

多行子查询

子查询的结果返回多行的,我们称之为多行子查询,大家想想看,既然子查询提供给主查询的结果有多条,那么是满足其中的一个,还是都要满足呢?不同的情况我们要用不同的关键词来表示

in:只要满足in里的任意一个条件结果即为真

all:满足all中的所有条件,结果才为真

any:满足any条件里的任意一个,结果即为真

in关键字;查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的

select ename,job,sal,deptno from emp where job in (select distinct job from

emp where deptno=10) and deptno<>10;

all关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

select ename, sal, deptno from EMP where sal > all(select sal from EMP where

deptno=30);

any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)

select ename, sal, deptno from EMP where sal > any(select sal from EMP where

deptno=30);

any是用于子查询,in是用于表达式列表,in也可以用于子查询,因为多行子查询的返回结果有多个,就组成一个表达式列表


多列子查询

单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句

例如:查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人

select ename from emp where (deptno, job)=(select deptno, job from emp

where ename='SMITH') and ename <> 'SMITH';

在from子句中使用子查询

我们都知道from表示查询的属于来源于哪些表,如果在from中使用子查询,意味着把子查询的结果作为一张表,给主查询提供数据来源

例如:显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资

select ename, deptno, sal, format(asal,2) from emp, (select avg(sal) as asal, deptno as dt from emp group by deptno) as tmp where emp.sal > tmp.asal and emp.deptno=tmp.dt;

要求:查找每个部门工资最高的人的姓名、工资、部门、最高工资,代码如下

select emp.ename, emp.sal, emp.deptno, ms from emp, (select max(sal) as ms, deptno from emp group by deptno) as tmp where emp.deptno=tmp.deptno and emp.sal=tmp.ms;

合并查询

联合查询就比较容易理解了,联合查询就是通过union, union all 关键词将多个select的执行结果合并

union:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行

例如:将工资大于2500或职位是MANAGER的人找出来emp

select * from emp where sal > 2500 union select * from emp where job = 'MANAGER';

union all: 该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行

这个简单来说就是不去重,使用和上述同样的例子,大家感受一下

 

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
存储 关系型数据库 MySQL
mysql数据库查询时用到的分页方法有哪些
【8月更文挑战第16天】在MySQL中,实现分页的主要方法包括:1)使用`LIMIT`子句,简单直接但随页数增加性能下降;2)通过子查询优化`LIMIT`分页,提高大页码时的查询效率;3)利用存储过程封装分页逻辑,便于复用但需额外维护;4)借助MySQL变量实现,可能提供更好的性能但实现较复杂。这些方法各有优缺点,可根据实际需求选择适用方案。
|
5天前
|
SQL JavaScript 前端开发
vue中使用分页组件、将从数据库中查询出来的数据分页展示(前后端分离SpringBoot+Vue)
这篇文章详细介绍了如何在Vue.js中使用分页组件展示从数据库查询出来的数据,包括前端Vue页面的表格和分页组件代码,以及后端SpringBoot的控制层和SQL查询语句。
vue中使用分页组件、将从数据库中查询出来的数据分页展示(前后端分离SpringBoot+Vue)
|
5天前
|
JavaScript 前端开发 数据处理
在vue中的form表单中下拉框中的数据来自数据库查询到的数据
这篇文章介绍了如何在Vue框架的表单中将下拉框的数据通过后端接口从数据库动态查询并加载,包括前端HTML代码、JavaScript数据处理、后端接口实现以及表单提交的完整流程。
在vue中的form表单中下拉框中的数据来自数据库查询到的数据
|
6天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
1天前
|
关系型数据库 MySQL 数据库
成功解决:Navicat 连接虚拟机Docker中的mysql数据库失败(仅限某些特殊情况)
这篇文章介绍了在Ubuntu环境中使用Docker部署Flask项目的方法,包括创建测试项目、设置数据库、构建Flask和Nginx镜像以及容器编排,其中使用了MySQL 5.7作为数据库,Flask 2.0.2作为Web框架,Gunicorn 20.1.0作为应用服务器,Nginx 1.21.4作为反向代理,并解决了Navicat连接Docker中的MySQL数据库失败的问题。
|
5天前
|
数据库 知识图谱
知识图谱(Knowledge Graph)- Neo4j 5.10.0 Desktop & GraphXR 连接自建数据库
知识图谱(Knowledge Graph)- Neo4j 5.10.0 Desktop & GraphXR 连接自建数据库
12 0
|
5天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
6天前
|
存储 关系型数据库 MySQL
MySQL——数据库备份上传到阿里云OSS存储
MySQL——数据库备份上传到阿里云OSS存储
23 0
|
1天前
|
SQL 存储 关系型数据库
数据库-MySQL-01(一)
数据库-MySQL-01(一)
13 4
|
6天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。

热门文章

最新文章