MySQL基础篇(运算符、排序分页、多表查询、函数)-3

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL基础篇(运算符、排序分页、多表查询、函数)

MySQL基础篇(运算符、排序分页、多表查询、函数)-2

https://developer.aliyun.com/article/1425387


单行函数


不同DBMS函数的差异

DBMS 之间的差异性很大,远大于同一个语言不同版本之间的差异。

比如:大部分DBMS使用(||)或者(+)来做拼接符,而在MySql中的字符拼接函数为concat()。


采用SQL函数的代码可移植性是很差的

MySQL的内置函数及分类

MySQL提供的内置函数从实现的功能角度可以分为:

  • 数值函数
  • 字符串函数
  • 日期和时间函数
  • 流程控制 函数
  • 加密与解密函数
  • 获取MySQL信息函数
  • 聚合函数


分为两大类:

  • 单行函数
  • 操作数据对象
  • 接受参数返回一个结果
  • 只对一行进行变换
  • 每行返回一个结果
  • 可以嵌套
  • 参数可以是一列或一个值
  • 聚合函数(或分组函数)


数值函数、字符串函数、日期和时间函数

CONCAT(s1,s2,…,sn) 连接s1,s2,…,sn为一个字符串
CONCAT_WS(x, s1,s2,…,sn) 同CONCAT(s1,s2,…)函数,但是每个字符串之间要加上x
TRUNCATE(x,y) 返回数值 x 保留到小数点后 y 位的值(与 ROUND 最大的区别是不会进行四舍五入)


SYSDATE() 返回当前日期和时间
NOW() 返回当前日期和时间
DATEDIFF(d1,d2) 计算日期 d1->d2 之间相隔的天数
DATE_FORMAT(date,format) date参数是合法的日期。format 规定日期/时间的输出格式


https://www.runoob.com/mysql/mysql-functions.html


流程控制函数

流程处理函数可以根据不同的条件,执行不同的处理流程,可以在SQL语句中实现不同的条件选择。 MySQL中的流程处理函数主要包括IF()、IFNULL()和CASE()函数。

函数 用法
IF(value,value1,value2) 如果value的值为TRUE,返回value1, 否则返回value2
IFNULL(value1, value2) 如果value1不为NULL,返回value1,否 则返回value2
CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2 … [ELSE resultn] END 相当于Java的if…else if…else…

CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN 值1 … [ELSE 值n] END相当于Java的switch…case…


示例

Mysql会把函数当成字段,所以我们一般给它起个别名

-- 1、IF(value,value1,value2)
-- 如果value的值为TRUE,返回value1, 否则返回value2
SELECT IF(1>0,'data1','data2')
-- 2、IFNULL(value1, value2)
-- 如果value1不为NULL,返回value1,否 则返回value2
SELECT IF(1>0,'data1','data2')
-- 3、CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2 .... [ELSE resultn] END
-- 相当于Java的if...else if...else...
SELECT
  last_name,
  salary,
CASE
  WHEN salary >= 15000 THEN '高薪'  
  WHEN salary >= 10000 THEN '底薪' 
  ELSE '半残' 
END 'details'
FROM
  employees
-- 4、CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN 值1 .... [ELSE 值n] END
-- 相当于Java的switch...case...
SELECT
  last_name,
  salary,
CASE 
  salary >= 15000
  WHEN salary >= 15000 THEN '高薪' 
  WHEN salary >= 10000 THEN '底薪' 
  ELSE '半残' 
END 'details'
FROM
  employees

加密与解密、信息、其他函数

MySQL中内置了一些可以查询MySQL信息的函数,这些函数主要用于帮助数据库开发或运维人员更好地 对数据库进行维护工作。

MySQL中有些函数无法对其进行具体的分类,但是这些函数在MySQL的开发和运维过程中也是不容忽视 的。

**

练习

# 1.显示系统时间(注:日期+时间)
SELECT NOW()
# 2.查询员工号,姓名,工资,以及工资提高百分之20%后的结果(new salary)
SELECT
  employee_id,
  last_name,
  salary * 1.2 'new salary'
FROM
 employees
# 3.将员工的姓名按首字母排序,并写出姓名的长度(length)
SELECT
  employee_id,
  LENGTH( last_name ) last_name 
FROM
  employees 
ORDER BY
  first_name DESC;
# 4.查询员工id,last_name,salary,并作为一个列输出,别名为OUT_PUT
SELECT
  CONCAT( employee_id, last_name, salary ) OUT_PUT 
FROM
  employees
# 5.查询公司各员工工作的年数、工作的天数,并按工作年数的降序排序
SELECT
  DATEDIFF(SYSDATE(),hire_date) / 365 worked_years,
  DATEDIFF(SYSDATE(),hire_date) worked_days
FROM
  employees
ORDER BY 
worked_years DESC
# 6.查询员工姓名,hire_date , department_id,满足以下条件:雇用时间在1997年之后,department_id
-- 为80 或 90 或110, commission_pct不为空
SELECT
  last_name,
  hire_date,
  department_id
FROM
  employees
WHERE
  DATE_FORMAT(hire_date,'%Y') >= '1997'
AND
  department_id IN (80,90,110)
AND
  commission_pct IS NOT NULL
# 7.查询公司中入职超过10000天的员工姓名、入职时间
SELECT
  last_name,
  hire_date
FROM
  employees
WHERE
  DATEDIFF(NOW(),hire_date) > 10000
# 8.做一个查询,产生下面的结果
-- -- <last_name> earns `<salary>` monthly but wants <salary*3>
-- -- Dream Salary
-- -- King earns 24000 monthly but wants 72000
SELECT
  CONCAT(
    last_name,
    ' earns ',
    TRUNCATE ( salary, 0 ),
    ' monthly but he wants ',
  TRUNCATE ( salary * 3, 0 )) 'Dream Salary'
FROM
  employees
-- 9.使用CASE-WHEN,按照下面的条件:
-- -- job       grade
-- -- AD_PRES   A
-- -- ST_MAN    B
-- -- IT_PROG   C
-- -- SA_REP    D
-- -- ST_CLERK  E
-- -- 产生下面的结果
-- -- Last_name   Job_id    Grade
-- -- king        AD_PRES   A
SELECT
  last_name Last_name,
  job_id Job_id,
CASE
    job_id 
    WHEN 'AD_PRES' THEN
    'A' 
    WHEN 'ST_MAN' THEN
    'B' 
    WHEN 'IT_PROG' THEN
    'C' 
    WHEN 'SA_REP' THEN
    'D' 
    WHEN 'ST_CLERK' THEN
    'E' ELSE 'F' 
  END Grade 
FROM
  employees

聚合函数

聚合函数作用于一组数据,并对一组数据返回一个值。

聚合函数类型

  • AVG()
  • SUM()
  • MAX()
  • MIN()
  • COUNT()


COUNT函数

作用

  • 计算指定字段在查询结构中出现的个数
  • COUNT(数字)这种情况是属于用数据库中不存在的字段表示,每一条记录它都会当成这个数字来计算个数。用其他数字也是一样
  • ff890003ec39805f9417becb2c28db53_4261ae9abe011c3403a5dc6e762d2f7d.png
  • 如果计算表中有多少条记录,如何实现?
  • COUNT(*)
  • COUNT(1)
  • COUNT(具体字段):不一定对,如果该字段包含NULL值,那么NULL值是不会被包含进记录计算的


能不能使用count(列名)替换count(*)?

不要使用 count(列名)来替代 count() , count() 是 SQL92 定义的标准统计行数的语法,跟数 据库无关,跟 NULL 和非 NULL 无关。


说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。


count(列名)和count(*)效率

如果使用的是MyISAM 存储引擎,则三者效率相同,都是o(1)


如果使用的是InnoDB存储引擎,则三者效率:cOUNT(*) =COUNT(1)>COUNT(字段)


聚合函数示例

-- 1、可以对数值型数据使用AVG 和 SUM 函数。
SELECT 
  AVG(salary),
  MAX(salary),
  MIN(salary),
  SUM(salary)
FROM
  employees
6461.682243 24000.00  2100.00 691400.00 
-- 2、COUNT(*)返回表中记录总数,适用于任意数据类型。  
SELECT
  COUNT(*)
FROM
  employees;
107


GROUP BY的使用

很形象的图,下次忘了GROUP BY怎么用的话就想想这个图!!!

按照部门分组:

单个部门进行分组:
SELECT
  department_id,
  AVG(salary),
  SUM(salary)
FROM
  employees
多个部门进行分组:
SELECT
  department_id,
  job_id,
  AVG( salary ) 
FROM
  employees 
GROUP BY
  department_id,
  job_id


GROUP BY注意事项

1、SELECT中出现的非组函数的字段必须声明在GPOUP BY中。

以下是错误的示范:

last_name属于普通的字段,所以它必须声明在GROUP BY中

SELECT
  department_id,
  job_id,
  last_name,
  AVG( salary ) 
FROM
  employees 
GROUP BY
  department_id,
  job_id

反之,GROUP BY中声明的字段可以不出现在SELECT中。

SELECT
  department_id,
  AVG( salary ) 
FROM
  employees 
GROUP BY
  department_id,
  job_id


2、GROUP BY 声明在FROM后面、WHERE后面,ORDER BY前面、LIMIT前

3、使用 WITH ROLLUP 关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所 有记录的总和,即统计记录数量。

SELECT
  department_id,
  AVG( salary ) 
FROM
  employees 
GROUP BY
  department_id,
  job_id WITH ROLLUP

当使用ROLLUP时,不能同时使用ORDER BY子句进行结果排序,即ROLLUP和ORDER BY是互相排斥 的。

HAVING的使用

HAVING的作用就是过滤分组

但使用有以下条件:


  • 行已经被分组
  • 使用了聚合函数
  • 满足HAVING 子句中条件的分组将被显示
  • HAVING 不能单独使用,必须要跟 GROUP BY 一起使用
SELECT
  department_id,
  AVG( salary ) 
FROM
  employees 
GROUP BY
  department_id,
  job_id
HAVING
  MAX(salary) >10000

如果过滤条件中使用了聚合函数,则必须使用HAVING来替换WHERE。否则,报错。

HAVING 必须声明在GROUP BY 的后面。

WHERE和HAVING的对比

  • 区别1:
  • WHERE 后面跟筛选条件的时候不能跟聚合函数
  • HAVING和GROUP BY配合使用,可以用聚合函数当筛选条件
  • 这决定了,在需要对数据进行分组统计的时候,HAVING 可以完成 WHERE 不能完成的任务。这是因为, 在查询语法结构中,WHERE 在 GROUP BY 之前,所以无法对分组结果进行筛选。HAVING 在 GROUP BY 之 后,可以使用分组字段和分组中的计算函数,对分组的结果集进行筛选,这个功能是 WHERE 无法完成 的。另外,WHERE排除的记录不再包括在分组中。
  • 区别2:
  • 如果需要通过连接从关联表中获取需要的数据,WHERE 是先筛选后连接,而 HAVING 是先连接 后筛选。
  • 这一点,就决定了在关联查询中,WHERE 比 HAVING 更高效。因为 WHERE 可以先筛选,用一 个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也比较高。HAVING 则需要 先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用 的资源就比较多,执行效率也较低。


WHERE 先筛选数据在关联,执行效率高 不能使用分组中的计算函数进行筛选
HAVING 可以使用分组中的计算函数 在最后的结果集中进行筛选,执行效率低


开发中的选择:

WHERE和HAVING并不冲突,我们可以同时使用它们,更好的发挥它们的优点

包含分组统计函数条件用HAVING,普通条件用WHERE。

当数据量特别大的时候,运行效率会有很 大的差别。


SELECT的执行原理

SELECT ...,....,...
FROM ... JOIN ...
ON 多表的连接条件
JOIN ...
ON ...
WHERE 不包含组函数的过滤条件
AND/OR 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
#其中:
#(1)from:从哪些表中筛选
#(2)on:关联多表查询时,去除笛卡尔积
#(3)where:从表中筛选的条件
#(4)group by:分组依据
#(5)having:在统计结果中再次筛选
#(6)order by:排序
#(7)limit:分页


SELECT 查询时的两个顺序:


  • 关键字的顺序是不能颠倒的
  • SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT…
  • SELECT 语句的执行顺序(在 MySQL 和 Oracle 中,SELECT 执行顺序基本相同)
  • FROM -> WHERE -> GROUP BY -> HAVING -> SELECT 的字段 -> DISTINCT -> ORDER BY -> LIMIT

f8bdafd8e8f19083afd27ae1e9adf3d7_f13c678a1ea0afdcbc1c2858fa864701.png

练习

#1.where子句可否使用组函数进行过滤?
不可以,where后面一般跟非组函数条件进行过滤
HAVING后面一般跟组函数进行过滤
#2.查询公司员工工资的最大值,最小值,平均值,总和
SELECT
  MAX(salary),
  MIN(salary),
  AVG(salary),
  SUM(salary)
FROM
  employees
#3.查询各job_id的员工工资的最大值,最小值,平均值,总和
SELECT
  job_id,
  MAX(salary),
  MIN(salary),
  AVG(salary),
  SUM(salary)
FROM
  employees
GROUP BY
  job_id
#4.选择具有各个job_id的员工人数
-- COUNT()这里的参数可填*,1,employee_id
-- 但是要注意如果填字段名,count不计算空值
SELECT
  job_id,
  COUNT(*)
FROM
  employees
GROUP BY
  job_id
# 5.查询员工最高工资和最低工资的差距(DIFFERENCE)
SELECT
  MAX( salary ) - MIN( salary ) 'DIFFERENCE' 
FROM
  employees
# 6.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内
SELECT
  manager_id,
  MIN( salary ) 
FROM
  employees 
WHERE
--  salary > 6000 题中说到最低工资,所以应该用聚合函数MIN来求得最低工资然后进行判断
  manager_id IS NOT NULL 
GROUP BY
  manager_id
HAVING
  MIN(salary) >= 6000
# 7.查询所有部门的名字,location_id,员工数量和平均工资,并按平均工资降序
SELECT
  d.department_name,
  d.location_id,
  COUNT(employee_id),
  AVG( salary ) '平均工资'
FROM
  departments d
  LEFT JOIN employees e ON d.department_id = e.department_id 
GROUP BY
  department_name,location_id 
ORDER BY
  '平均工资' DESC
# 8.查询每个工种、每个部门的部门名、工种名和最低工资
-- 这里的每个其实也可看成所有!
-- 最后结果出现很多空值是因为部门有很多是没有人的,那么就会出现job_id和salary为空的情况
SELECT
  d.department_name,
  e.job_id,
  MIN( salary ) 
FROM
  departments d
  LEFT JOIN employees e ON d.department_id = e.department_id 
GROUP BY
  department_name,
  job_id

易错点

查询所有部门的名字,location_id,员工数量和平均工资,并按平均工资降序


这里部门表左连接员工表,而部门表有很多空部门,这样员工表和部门表连接时就会出现很多空值。如果我们在用COUNT(*)计算员工数量时,那么它会把NULL的也给算进去,所以这里呢COUNT应该填字段名,让它进行一个排NULL操作

9764bf049e31f74108d9a426c03f6618_53b0f7a2df1e84f46044e1adb2c56097.png所以

SELECT
  d.department_name,
  d.location_id,
  COUNT(employee_id),
  AVG( salary ) '平均工资'
FROM
  departments d
  LEFT JOIN employees e ON d.department_id = e.department_id 
GROUP BY
  department_name,location_id 
ORDER BY
  '平均工资' DESC


查询每个工种、每个部门的部门名、工种名和最低工资


这里的每个其实也可看成所有!

最后结果出现很多空值是因为部门有很多是没有人的,那么就会出现job_id和salary为空的情况


查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,没有管理者的员工不计算在内


这里不能在WHERE后加salary > 6000


题中说到最低工资,所以应该用聚合函数MIN来求得最低工资然后进行判断

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
23天前
|
JSON 关系型数据库 MySQL
Mysql(5)—函数
MySQL提供了许多内置的函数以帮助用户进行数据操作和分析。这些函数可以分为几类,包括聚合函数、字符串函数、数值函数、日期和时间函数、控制流函数等。
67 1
Mysql(5)—函数
|
4天前
|
关系型数据库 MySQL Serverless
MySQL函数
最常用的MySQL函数,包括聚合函数,字符串函数,日期时间函数,控制流函数等
|
8天前
|
SQL NoSQL 关系型数据库
2024Mysql And Redis基础与进阶操作系列(5)作者——LJS[含MySQL DQL基本查询:select;简单、排序、分组、聚合、分组、分页等详解步骤及常见报错问题所对应的解决方法]
MySQL DQL基本查询:select;简单、排序、分组、聚合、分组、分页、INSERT INTO SELECT / FROM查询结合精例等详解步骤及常见报错问题所对应的解决方法
|
17天前
|
缓存 关系型数据库 MySQL
一文彻底弄懂MySQL优化之深度分页
【10月更文挑战第24天】本文深入探讨了 MySQL 深度分页的原理、常见问题及优化策略。首先解释了深度分页的概念及其带来的性能和资源问题。接着介绍了基于偏移量(OFFSET)和限制(LIMIT)以及基于游标的分页方法,并分析了它们的优缺点。最后,提出了多种优化策略,包括合理创建索引、优化查询语句和使用数据缓存,帮助提升分页查询的性能和系统稳定性。
|
1月前
|
SQL 搜索推荐 关系型数据库
MySQL 如何实现 ORDER BY 排序?
本文详细解析了MySQL中`ORDER BY`的实现原理及优化方法。通过解析与优化、执行及多种优化技术,如索引利用、内存排序、外部排序等,帮助你提升排序性能。了解其背后的机制,可显著优化查询效率。
21 4
|
8天前
|
SQL NoSQL 关系型数据库
|
1月前
|
存储 SQL 关系型数据库
MySQL 存储函数及调用
MySQL 存储函数及调用
32 3
|
19天前
|
关系型数据库 MySQL 数据库
mysql中tonumber函数使用要注意什么
在处理这类转换操作时,考虑周全,利用提供的高性能云服务器资源,可以进一步提升数据库处理效率,确保数据操作的稳定性和安全性,尤其是在处理大量数据转换和运算密集型应用时。
61 0
|
22天前
|
关系型数据库 MySQL 数据处理
企业级应用 mysql 日期函数变量,干货已整理
本文详细介绍了如何在MySQL8.0中使用DATE_FORMAT函数进行日期格式的转换,包括当日、昨日及不同时间段的数据获取,并提供了实际的ETL应用场景和注意事项,有助于提升数据处理的灵活性和一致性。
37 0
|
23天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
56 3
Mysql(4)—数据库索引