暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL之DQL语句(四)

GrowthDBA 2021-09-08
537

今天是SELECT语句的第四篇,主要介绍计算字段、数据处理函数的使用。文章摘录自Ben Forta的《MySQL必知必会》。今天的内容同样简单而重要,一起开始今天的学习吧!

01

创建计算字段

  • 计算字段:

存储在数据库表中的数据一般不是应用程序所需要的格式,举几个例子:
* 如果想在一个字段中既显示公司名,又显示公司地址,但这两个信息一般包含在不同的列表中。
* 城市、州和邮政编码存储在不同的列中(应该这样),但邮件标签打印程序却需要把它们作为一个恰当格式的字段检索出来。
* 列数据是大小写混合的,但报表程序需要把所有的数据按大写表示出来。
* 物品订单表存储物品的价格和数量,但不需要存储每个物品的总价格(用价格乘以数量即可)。为打印发票,需要物品的总价格。
* 需要根据表数据进行总数、平均数计算或其他计算。
在上述的每个例子中,存储在表中的数据都不是应用程序所需要的。我们需要直接从数据库中检索出转换、计算或格式化的数据;而不是检索出数据,然后再在客户机应用程序或报告程序中重新格式化。
这就是计算字段发挥作用的所在了。与前面各章介绍过的列不同,计算字段并不实际存在于数据库表中。计算字段是运行时在SELECT语句内创建的
重要的是要注意到,只有数据库知道SELECT语句中哪些列是实际的表列,哪些列是计算字段。从客户机(如应用程序)的角度来看,计算字段的数据是以与其他列的数据相同的方式返回的
  • 拼接字段:

拼接(concatenate)将值联结到一起构成单个值。解决办法是把两个列拼起接起来。在MySQL的SELECT语句中,可以使用CONCAT()函数来拼接两个列。
SELECT CONCAT(vend_name,'(',vend_country,')') FROM vendors ORDER BY vend_name;

CONCAT()拼接串,即把多个串连接起来形成一个较长的串。CONCAT()需要一个或多个指定的串,各个串之间逗号分隔

之前的文章提到过删除数据右侧多余的空格来整理数据,这可以使用MySQL的RTRIM()函数来完成。
SELECT CONCAT(RTRIM(vend_name),'(',RTRIM(vend_country),')') FROM vendors ORDER BY vend_name;

RTRIM()函数去掉值右边的所有空格。通过使用RTRIM(),各个列都进行了整理。MySQL除了支持RTRIM()(去掉串右边的空格),还支持LTRIM()(去掉串左边的空格)以及TRIM()(去掉串左右两边的空格)

使用别名,从前面的输出可以看出,SELECT语句拼接地址字段工作得很好,但此新计算列的名字是什么呢?实际上它没有名字,它只是一个值。如果仅在SQL查询工具中查看一下结果,这样没什么不好。但是,一个未命名的列不能用于客户机应用中,因为客户机没有办法引用它。为了解决这个问题,SQL支持列别名。别名(alias)是一个字段或值的替换名。别名用AS关键字赋予
SELECT CONCAT(RTRIM(vend_name),'(',RTRIM(vend_country),')') AS vend_title FROM vendors ORDER BY vend_name;

SELECT语句本身与以前使用的相同,只不过这里的语句中计算字段之后跟了文本AS vend_title它指示SQL创建一个包含指定计算的名为vend_title的计算字段从输出可以看到,结果以前的相同,但现在列名vend_title,任何客户机应用都可以按名引用这个列就像它是一个实际的表列一样。

别名的其他用途:别名还有其他用途。常见的用途包括在实际的表列名包含不符合规定的字符(如空格)时重新命名它,在原来的名字含混或容易误解时扩充它,等等。别名有时也被称为导出列(derived column),不管称为什么,它们所代表的都是相同的东西。
  • 执行算数计算:

计算字段的另一常见用途是对检索出的数据进行算数计算。检索出订单号20005中的所有物品:
SELECT prod_id,quantity,item_price FROM orderitems WHERE order_num = 20005;

item_price列包含单中每项物品的单价汇总物品价格(单价乘以订购数量

SELECT prod_id,quantity,item_price,quantity*item_price AS expanded_price FROM orderitems where order_num=20005;

输出中显示expanded_price列为一个计算字段,此计算为quantity*item_price。客户机应用现在可以使用这个新计算列,就像使用其他列一样。

MySQL支持的基本算术操作符如下。(此外,圆括号可用来区分优先顺序)

操作符说明
+
-
*
/
SELECT提供了测试试验函数与计算的一个很好的办法。虽然SELECT通常用来从表中检索数据,但可以省略FROM子句以便简单地访问和处理表达式。例如,SELECT 3*2;将返回6,SELECT TRIM(' abc ');将返回abc,而SELECT NOW()利用NOW()函数返回当前日期和时间。通过这些例子,可以明白如何根据需要使用SELECT进行试验。

02

使用数据处理函数

  • 函数:

与其他大多数计算机语言一样,SQL支持利用函数来处理数据。函数一般是在数据上执行的,它给数据的转换和处理提供了方便。TRIM()就是一个函数。
能运行在多个系统上的代码称为可移植的(portable)。相对来说,多数SQL语句是可移植的,在SQL实现之间有差异时,这些差异通常不那么难处理。而函数的可移植性却不强。几乎每种主要的DBMS的实现都支持其他实现不支持的函数,而且有时差异还很大。
为了代码的可移植,许多SQL程序员不赞成使用特殊实现的功能。虽然这样做很有好处,但不总是利于应用程序的性能。如果不使用这些函数,编写某些应用程序代码会很艰难。必须利用其它方法来实现DBMS非常有效地完成工作。如果你决定使用函数,应该保证做好代码注释,以便以后你(或其他人)能确切地知道所编写SQL代码的含义。
  • 使用函数:

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

SELECT vend_name,UPPER(vend_name) AS vend_name_upcase FROM vendors ORDER BY vend_name;

正如所见,UPPER()将文本转换为大写

一些常用的文本处理函数:

函数说明
LEFT()返回串左边的字符
LENGTH()返回串的长度
LOCATE()找出串的一个子串
LOWER()将串转换为小写
LTRIM()去掉串左边的空格
RIGHT()返回串右边的字符
RTRIM()去掉串右边的空格
TRIM()去掉串左右两边的空格
SOUNDEX()返回串的SOUNDEX值
SUBSTRING()返回子串的字符
UPPER()将串转换为大写

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

举个栗子🌰:

customers表中有一个顾客Coyote Inc.,其联系名为Y. Lee。但如果这是输入错误,此联系名实际应该是Y. Lie,怎么办?

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

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

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

  • 日期和时间处理函数:

日期和时间采用相应的数据类型和特殊的格式存储,以便能快速和有效地排序或过滤,并且节省物理存储空间。一般,应用程序不使用用来存储日期的时间的格式,因此日期和时间函数总是被用来读取、统计和处理这些值。由于这个原因,日期和时间函数在MySQL语言中具有重要的作用。

常用的日期和时间处理函数:

函数说明
ADDDATE()增加一个日期(天、周等)
ADDTIME()增加一个时间(时、分等)
CURDATE()返回当前日期
CURTIME()返回当前时间
DATE()返回日期时间的日期部分
DATEDIFF()计算两个日期之差
DATE_ADD()高度灵活的日期运算函数
DATE_FORMAT()返回一个格式化的日期或时间串
DAY()返回一个日期的天数部分
DAYOFWEEK()对于一个日期,返回对应的星期几
HOUR()返回一个时间的小时部分
MINUTE()返回一个时间的分钟部分
MONTH()返回一个时间的月份部分
NOW()返回当前日期和时间
SECOND()返回一个时间的秒部分
TIME()返回一个日期时间的时间部分
YEAR()返回一个日期的年份部分

首先需要注意的是MySQL使用的日期格式。无论你什么时候指定一个日期,不管是插入或更新表值还是用WHERE子句进行过滤,日期必须为格式yyyy-mm-dd。因此,2005年9月1日,给出为2005-09-01。虽然其他的日期格式可能也行,但这是首选的日期格式,因为它排除了多性(如,04/05/06是2006年5月4日或2004年5月6日或2006年4月5日...)。

应该总是使用4位数的年份值:MySQL处理00-69为2000-2069,处理70-99为1970-1999,虽然它们可能是打算要的年份,但使用完整的4位数字年份更可靠,因为MySQL不必做出任何假定。

基本的日期比较应该很简单:

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

但是WHERE 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'失败。即使给出具有该日期的一行,也不会把它检索出来,因为WHERE匹配失败。
解决办法是指示MySQL仅将给出的日期部分进行比较,而不是将给出的日期与整个列值进行比较为此,必须使用DATE()函数,更可靠的SELECT语句为:
SELECT cust_id,order_num FROM orders WHERE DATE(order_date)='2005-09-01';

如果要的仅仅是日期,使用DATE()是一个良好的习惯,即使你知道相应的列只包含日期也是如此。在你只想要时间时应该使用TIME()函数

检索出2005年9月下的所有订单:

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

另一种办法:

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

  • 数值处理函数:

数值处理函数仅处理数值数据。这些函数一般主要用于代数、三角、几何运算,因此没有串或时间-日期处理函数的使用那么频繁。具有讽刺意味的是,在主要DBMS的函数中,数值函数是最一致最统一的函数。
函数说明
ABS()返回一个数的绝对值
COS()返回一个角度的余弦
EXP()返回一个数的指数值
MOD()返回除操作的余数
PI()返回圆周率
RAND()返回一个随机数
SIN()返回一个角度的正弦
SQRT()返回一个数的平方根
TAN()返回一个角度的正切

03

小结

今天主要介绍了计算字段以及如何创建计算字段,同时介绍了如何使用数据处理函数。SOUNDEX函数不多见,需要注意。站在巨人肩膀上,每天进步一点点。

end

文章转载自 GrowthDBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论