MySQL快速回顾:计算字段与函数

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL快速回顾:计算字段与函数

9.1 计算字段

存储在数据库表中的数据一般不是应用程序所需要的格式。比如:

  • 如果想要在一个字段中既显示公司名,又显示公式的地址,但这两个信息一般包含在不同的表列中。
  • 城市、州和邮政编码存储在不同的列中,但邮件标签打印程序却需要把它们作为一个恰当格式的字段检索出来。
  • 列数据是大小写混合的,但报表程序需要把所有数据按大写表示出来。

在上面举的例子中,存储在表中的数据都不是应用程序所需要的。我们需要直接数据库中检索出转换、计算或格式化过的数据;而不是检索出数据,然后在客户机应用程序或报告程序中重新格式化。

所以就需要计算字段。计算字段并不实际存储于数据库表中,而是运行时在SELECT语句内创建的。

这里的字段(field)基本上跟列(column)的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段通常用在计算字段的连接上。

可在SQL语句内完成的许多转换和格式化工作都可以直接在客户机应用程序内完成。但是一般来说,在数据库服务器上完成这些操作比在客户机中完成要快得多,因为DBMS是设计来快速地完成这种处理的。

9.1.1 计算字段的使用

举一个创建由两列组成的标题的简单例子。

vendors表包含供应商名和位置信息。假如要生成一个供应商报表,需要在供应商的名字中按照name(location)这样的格式列出供应商的位置。

此报表需要单个值,而表中数据存储在两个列vend_name和vend_country中。此外,需要用括号将vend_country括起来,这些东西都没有明确存储在数据库表中。来看看如何用SELECT来编写这样的格式。

拼接(concatenate)将值联结到一起构成单个值。

解决的方法就是将两个列拼接起来。在MySQL的SELECT语句中,可使用CONCAT()函数来拼接两个列。

多数DBMS使用+或者||来实现拼接,而MySQL则使用Concat()函数来实现。当把SQL语句转换成MySQL语句时一定要把这个区别铭记在心。

结果:

SELECT CONCAT(vend_name, '(', vend_country, ')')
 FROM vendors
 ORDER BY vend_name;

输出:

+-------------------------------------------+
| CONCAT(vend_name, '(', vend_country, ')') |
+-------------------------------------------+
| ACME(USA)                                 |
| Anvils R Us(USA)                          |
| Jet Set(England)                          |
| LT Supplies(USA)                          |
+-------------------------------------------+
4 rows in set (0.06 sec)

解释:

  • CONCAT()拼接串),即把多个串连接起来形成一个较长的串。CONCAT()需要一个或多个指定的串,各个串之间用逗号分隔。(关于更多函数的使用后面会讲)
  • 上面的SELECT语句连接以下4个元素:
  • 存储在vend_name列中的名字;
  • 包括一个空格和一个左圆括号的串;
  • 存储在vend_country列中的国家;
  • 包括一个右圆括号的串。

9.1.2 使用别名

你拿上面那条语句去执行,会发现新计算出的列名,列名好长而且列名的意义不能明确看出。实际上它是没有名称,它只是一个值。如果仅在SQL查询工具中查看一下结果,这样没什么不好。但是,一个未命名的列不能用于客户机应用中,因为客户机没有办法引用它。这时候SQL就引出别名。

别名(alias)是一个字段或值的替换名。别名用AS关键字赋予。

使用别名修改上面的SQL语句

SELECT CONCAT(vend_name, '(', vend_country, ')')
 AS vend_title
 FROM vendors
 ORDER BY vend_name;

AS也可省略,只要在需要重命名的后面空一格。

SELECT CONCAT(vend_name, '(', vend_country, ')')
  vend_title
 FROM vendors
 ORDER BY vend_name;

输出:

+------------------+
| vend_title       |
+------------------+
| ACME(USA)        |
| Anvils R Us(USA) |
| Jet Set(England) |
| LT Supplies(USA) |
+------------------+
4 rows in set (0.06 sec)

这样任何客户机都可以按别名引用这个列,看起来是一个实际的表列一样。

别名不止用于计算字段中,还可以在实际的表列名包含不符合规定的字符(含空格)时重新命名它,在原来的名字含混或容易误解时扩充它,等。但记住,并不是真正会去重命名表中的实际列名。

别名有时候也称为导出列(derived column),不管称为什么,它们所代表的都是相同的东西。

9.1.3 执行算术计算

计算字段的另一常见用途是读检索出的数据进行算术计算。比如,一个订单表order中含有物品价格price和物品数量quantity,需要求物品总价格。那么只需要 物品价格乘以物品数据即可。

SELECT order_id, order_price*order_quantiry 
 AS expanded_price
 FROM order;

MySQL算术操作符:+、-、*、/。

SELECT可用通过使用计算字段来测试。

SELECT 2*3;

小结:介绍了计算字段以及如何创建计算字段。此外还学了如何创建和使用别名,以便应用程序能引用计算字段。

9.2 函数

SQL支持利用函数来处理数据。

可移植性(portable): 能运行在多个系统上的代码。

多数SQL语句是可移植的,在SQL实现之间有差异时,这些差异通常不那么难处理。而函数的可移植性却不强。几乎每种主要的DBMS的实现都支持其他实现不支持的函数,而且有时差异还很大。

为了代码的可移植性,很多SQL程序员不赞成使用特殊实现的功能。虽然这样有好处,但是不使用这些函数,编写某些应用程序代码会很难。

如果决定使用函数,应该保证做好代码注释,以便以后你(或其他人)能确切地知道所编写的SQL代码的含义。

9.2.1 使用函数

大多数SQL实现支持以下类型的函数

  • 用于处理文本串(如删除或填充值,转换值为大写或小写)的文本函数
  • 用于在数值上进行算术操作(如返回绝对值,进行代数运算)的数值函数。
  • 用于处理日期和时间值并从这些值中提取特定成分(例如,返回两个日期之差,检查日期有效性等)的日期和时间函数。
  • 返回DBMS正使用的特殊信息(如返回用户登录信息,检查版本细节)的系统函数

9.2.2 文本处理函数

之前已经介绍TRIM():去空格的函数。类似的函数如下:

参考:菜鸟教程

函数 说明 演示
LEFT(s,n) 返回字符串 s 的前 n 个字符 返回字符串 runoob 中的前两个字符:SELECT LEFT('runoob',2) -- ru
RIGHT(s,n) 返回字符串 s 的后 n 个字符 返回字符串 runoob 的后两个字符:SELECT RIGHT('runoob',2) -- ob
LOWER(s) 将串转换为小写 把字符串 Runoob 全转小写: SELECT LOWER('Runoob') -- runoob
UPPER(s) 将串转换为大写 返回字符串 runoob 全转小写:SELECT UPPER('Runoob') -- RUNOOB
TRIM(s) 去掉串的左右空格 去掉字符串 空格runoob空格 的空格:SELECT TRIM(' runoob ') -- runoob
LTRIM(s) 去掉串左边的空格 去掉字符串 空格runoob空格 的左空格:SELECT LTRIM(' runoob ') -- runoob空格
RTRIM(s) 去掉串右边的空格 去掉字符串 空格runoob空格 的右空格:SELECT RTRIM(' runoob ') -- 空格runoob
SOUNDEX() 返回串的SOUNDEX值 看下面的解释
SUBSTRING(s, start, length) 从字符串 s 的 start 位置截取长度为 length 的子字符串 从字符串 RUNOOB 中的第 2 个位置截取 3个 字符:SELECT SUBSTRING("RUNOOB", 2, 3) AS ExtractString; -- UNO
LOCATE(s1,s) 从字符串 s 中获取 s1 的开始位置 获取 b 在字符串 abc 中的位置:SELECT LOCATE('st','myteststring'); -- 5返回字符串 abc 中 b 的位置:SELECT LOCATE('b', 'abc') -- 2
LENGTH() 返回串的长度 返回字符串 runoob 的长度:SELECT LENGTH('runoob') -- 6

上面的SOUNDEX需要进一步解释:SOUNDEX是一个而将任何文本串转换为描述其语音表示的字母数字模式的算法。SOUNDEX考虑了类似的发音字符和音节,使得能对串进行发音比较而不是字母比较。虽然SOUNDEX不是SQL概念,但MySQL(就像很大DBMS一样)都提供对SOUNDEX的支持。

比如,创建一张表名为customers,表中包含顾客(cust_name)和联系名(cust_contact)。

CREATE TABLE customers(
    cust_name varchar(20) PRIMARY KEY,
    cust_contact varchar(20)
);

现在假设有一个顾客Coyote Inc. , 其联系名为 Y.Lee。但如果这是输入错误的结果,此联系名实际应该是Y.Lie,怎么办?显然,按正确的联系名搜索不会返回数据,如下:

SELECT cust_name, cust_contact
FROM customers
WHERE cust_contact = 'Y.Lie';

输出:

Empty set

现在试下使用SOUNDEX()函数进行搜索,它匹配所有发音类似于Y.Lie的联系名:

SELECT cust_name, cust_contact
FROM customers
WHERE SOUNDEX(cust_contact) = SOUNDEX('Y.Lie');

输出:

+-------------+--------------+
| cust_name   | cust_contact |
+-------------+--------------+
| Coyote Inc. | Y.Lee        |
+-------------+--------------+
1 row in set (0.05 sec)

在这个例子中,WHERE子句使用SOUNDEX()函数来转换cust_contact列值和搜索串为它们的SOUNDEX值。因为Y.Lee和Y.lie发音相似,所以它们的SOUNDEX值匹配,因此WHERE子句正确地过滤了所需的数据。

9.2.3 日期和时间处理函数

日期和时间采用相应的数据类型和特殊的格式存储,以便快速和有效地排序或过滤,并节省物理存储空间。

一般,应用程序不使用来存储日期和时间的格式,因此日期和时间函数总是被用来读取、统计和处理这些值。所以,日期和时间函数在MySQL语言中很重要。

表格转载:菜鸟教程

函数 说明 演示
ADDDATE(d,n) 计算起始日期 d 加上 n 天的日期 SELECT ADDDATE("2020-01-15", 3);
SELECT ADDDATE("2020-01-15", INTERVAL 3 DAY);
->(2020-01-18)
ADDTIME(t,n) 时间 t 加上 n 秒的时间 SELECT ADDTIME('2011-11-11 11:11:11', 5);
->2011-11-11 11:11:16 (秒)
CURDATE() 返回当前日期 SELECT CURDATE();
->2020-01-15
CURTIME() 返回当前时间 SELECT CURTIME();
->16:41:01
DATE() 从日期或日期时间表达式中提取日期值 SELECT DATE("2020-01-15");
->2020-01-15
DATEDIFF(d1,d2) 计算日期 d1->d2 之间相隔的天数 SELECT DATEDIFF("2020-01-15","2020-01-4");
->11(前面的日期减去后面的日期)
DATE_ADD(d,INTERVAL expr type) 计算起始日期 d 加上一个时间段后的日期 SELECT ADDDATE('2011-11-11 11:11:11',1);
-> 2011-11-12 11:11:11 (默认是天)
SELECT ADDDATE('2011-11-11 11:11:11', INTERVAL 5 MINUTE);
-> 2011-11-11 11:16:11 (TYPE的取值与上面那个列出来的函数类似)
DATE_FORMAT(d,f) 按表达式 f的要求显示日期 d SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r')
-> 2011-11-11 11:11:11 AM
DAY(d) 返回日期值 d 的日期部分 SELECT DAY("2020-01-15");
-> 15
DAYOFWEEK(d) 日期 d 今天是星期几,1 星期日,2 星期一,以此类推 SELECT DAYOFWEEK("2020-01-15");
-> 4
HOUR(t) 返回 t 中的小时值 SELECT HOUR("2020-01-15 17:21");
-> 17
MINUTE(t) 返回 t 中的分钟值 SELECT MINUTE("2020-01-15 17:21");
-> 21
MONTH(d) 返回日期d中的月份值,1 到 12 SELECT MONTH("2020-01-15 17:21");
-> 1
NOW() 返回当前日期和时间 SELECT NOW();
-> 2020-01-15 17:24:18
MICROSECOND(date) 返回日期参数所对应的微秒数 SELECT MICROSECOND("2017-06-20 09:34:00.000023");
-> -> 23
TIME(expression) 提取传入表达式的时间部分 SELECT TIME("19:30:10");
-> 19:30:10
YEAR(t) 返回t日期中的年份 SELECT YEAR("2020-01-15 17:21");
-> 2020

更多参考:菜鸟教程

需要注意的是MySQL使用的日期格式。无论是什么时候指定一个日期,或是插入或更新等,日期必须为格式yyyy-mm-dd。所以,2020年1月15号,给出的是2020-01-15.虽然其他的日期格式可能也行,但这是首选的日期格式,因为它排除了多义性(如,04/05/06是2006年5月4号还是2006年4月5号或...)。

应该总是使用4位数字的年份。MySQL虽然支持2位数字的年份,比如处理00-69位2000-2069。虽然它们可能是打算要的年份,但使用完整的4位数字年份更可靠。

在数据库表中检索时间日期,比如:

SELECT cust_id, order_num
FROM orders
WHERE order_date = '2005-09-01';

这样写的 order_date = '2005-09-01' 可靠吗?如果order_date的数据类型是datetime,这种类型存储日期及时间值,那么在例表中的值全都具有时间值00:00:00,但实际上很可能并不总是这样。如果用当前日期和时间存储订单日期(因此我们得知道订单日期和下订单当前的时间),怎么办??比如,存储的order_date值为2005-09-01 11:30:05,则WHERE order_date = '2005-09-01'就失败。

解决的方式:让MySQL仅将给出的日期与列中的日期部分进行比较,而不是将给出的日期与整个列值进行比较。所以得使用DATE()函数。DATE(order_date)表示MySQL仅提取列的日期部分,所以修改如下:

SELECT cust_id, order_num
FROM orders
WHERE DATE(order_date) = '2005-09-01';

所以,对于日期的数据要特别注意,如果要的是日期,使用DATE(),如果要的是天,使用DAY(),如果要的是月,使用MONTH()等。最好明确要的是什么格式的日期,即使知道相应的列只包含日期也应该加上函数。

还有一种日期比较需要说明。如果要检索2005年9月下的所有订单,怎么办??简单的相等测试肯定不行,因为它也要匹配月份中的天数。提供以下的解决方法:

SELECT cust_id, order_num
FROM orders
WHERE DATE(order_date) BETWEEN '2005-09-01' AND '2005-09-30';

其中,BETWEEN操作符用来把2005-09-01和2005-09-30定义为一个要匹配的日期范围。

还有另一种:

SELECT cust_id, order_num
FROM orders
WHERE YEAR(order_date) = 2005 AND MONTH(order_date) = 9;

解释:YEAR()是一个从日期(或日期时间)中返回年份的函数。类似,MONTH从日期中返回月份。因此WHERE YEAR(order_date) = 2005 AND MONTH(order_date) = 9检索出order_date为2005年9月的所有行。

9.2.3 数值处理函数

数值处理函数仅处理数值数据。一般主要用于代数、三角或几何运算。

在主要DBMS的函数中,数值函数是最统一最一致的函数。

函数 说明
ABS(t) 返回数t的绝对值
COS(t) 返回角度为t的余弦
EXP(t) 返回数t的指数值
MOD(a, b) 返回除操作(a/b)的余数 = (a%b)
PI() 返回圆周率
RAND() 返回一个随机数
SIN(t) 返回角度为t的正弦
SQRT(t) 返回数t的平方根
TAN(t) 返回角度为t的正切

小结:介绍了如何使用SQL的数据处理函数,主要注意日期函数的使用。这些函数不需要死记硬背,忘了就拿出来看。当然,最好简单的函数就记一记,比如:ABS()、SQRT()、YEAR()、HOUR()、DAY()等这些。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
JSON 关系型数据库 MySQL
Mysql(5)—函数
MySQL提供了许多内置的函数以帮助用户进行数据操作和分析。这些函数可以分为几类,包括聚合函数、字符串函数、数值函数、日期和时间函数、控制流函数等。
70 1
Mysql(5)—函数
|
8天前
|
分布式计算 关系型数据库 MySQL
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型 图像处理 光通信 分布式计算 算法语言 信息技术 计算机应用
30 8
|
12天前
|
关系型数据库 MySQL Serverless
MySQL函数
最常用的MySQL函数,包括聚合函数,字符串函数,日期时间函数,控制流函数等
|
16天前
|
SQL NoSQL 关系型数据库
|
17天前
|
关系型数据库 MySQL Java
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
SpringBoot项目中mysql字段映射使用JSONObject和JSONArray类型
22 0
|
27天前
|
关系型数据库 MySQL 数据库
mysql中tonumber函数使用要注意什么
在处理这类转换操作时,考虑周全,利用提供的高性能云服务器资源,可以进一步提升数据库处理效率,确保数据操作的稳定性和安全性,尤其是在处理大量数据转换和运算密集型应用时。
84 0
|
30天前
|
关系型数据库 MySQL 数据处理
企业级应用 mysql 日期函数变量,干货已整理
本文详细介绍了如何在MySQL8.0中使用DATE_FORMAT函数进行日期格式的转换,包括当日、昨日及不同时间段的数据获取,并提供了实际的ETL应用场景和注意事项,有助于提升数据处理的灵活性和一致性。
40 0
|
8天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
22 4
|
6天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
19 1
|
15天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
76 1