MySQL必知必会——函数的使用

一、使用数据处理函数

1、函数

与其他大多数计算机语言一样,SQL支持利用函数来处理数据。函数一般是在数据上执行的,它给数据的转换和处理提供了方便。

函数没有SQL的可移植性强。 能运行在多个系统上的代码称为可移植的。相对来说,多数SQL语句是可移植的,而函数的可移植性不强。几乎每种主要的DBMS的实现都支持其他实现不支持的函数,而且有时候差异还会很大。
为了代码的移植性,许多SQL程序员不赞成使用特殊实现的功能。虽然这样做很有好处,但不总是利于应用程序的性能。如果不使用这些函数,编写某些应用程序代码会很艰难,必须利用其他方法来实现DBMS非常有效完成的工作。
如果你决定使用函数,应该保证做好代码的注释,以便以后你能确切地知道所编写的SQL代码的含义。

2、使用函数

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

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

2.1文本处理函数

上一篇博客已经看过一个文本处理的例子,其中使用RTrim()函数来除去列值右边的空格。下面的例子,使用Upper()函数

MariaDB [course]> SELECT vend_name,Upper(vend_name) AS vend_name_upcase
    -> FROM vendors
    -> ORDER BY vend_name;
+----------------+------------------+
| vend_name      | vend_name_upcase |
+----------------+------------------+
| ACME           | ACME             |
| Anvils R Us    | ANVILS R US      |
| Furball Inc.   | FURBALL INC.     |
| Jet Set        | JET SET          |
| Jouets Et Ours | JOUETS ET OURS   |
| LT Supplies    | LT SUPPLIES      |
+----------------+------------------+
6 rows in set (0.00 sec)

正如所见,Upper()函数将文本转换为大写。因此实例中每个供应商都列出两列 ,第一次为vendors表中存储的值,第二次作为列vend_name_upcase转换为大写。

函数 说明
Left() 返回串左边的字符
Length() 返回串的长度
Locate() 找出串的一个子串
Lower() 将串转换为小写
Right() 返回串右边的字符
Soundex() 返回串的SOUNDEX值
SubString() 返回子串的字符
Upper() 将串转换为大写

表中的SOUNDEX是一个将任何文本串转换为描述其语音表示的字母数字模式的算法。SOUNDEX()考虑了类似的发音字符和音节,使能对串进行发音比较而不是字母比较。虽然,SOUNDEX不是SQL概念,但MySQL都提供对它的支持。
下面给出一个使用Soundex()函数的例子。customer表中有一个顾客Coyote Inc.,其联系名为Y.Lee。但如果这是输入错误,此联系名实际应该是Y.Lie,按照正常的联系名搜索时不会返回数据的。

MariaDB [course]> SELECT cust_name,cust_contact
    -> FROM customers
    -> WHERE cust_contact =  'Y.Lie';
Empty set (0.00 sec)

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

MariaDB [course]> 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.00 sec)

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

2.2日期和时间处理函数

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

迄今为止,我们都是用比较数值和文本的WHERE子句过滤数据,但是数据经常也需要用时间来进行过滤。用日期时间进行过滤需要注意一些别的问题和使用特殊的MySQL函数。
首先需要注意的是MySQL使用的日期格式,无论你什么时候指定一个日期,不管是插入或更新表值还是用WHERE子句进行过滤,日期都必须为格式yyyy--mm--dd。因此,2005年9月1日给出为2005-09-01。虽然其他的日期格式可能也行,但是这是首选的日期格式,因为它排除了多义性。

MariaDB [course]> SELECT cust_id,order_num
    -> FROM orders
    -> WHERE order_date = '2005-09-01';
+---------+-----------+
| cust_id | order_num |
+---------+-----------+
|   10001 |     20005 |
+---------+-----------+
1 row in set (0.00 sec)

但是这样比较有时候会出问题,比如order_time的数据类型为datetime,这种类型存储日期和时间值,格式为'2005-09-01 11:30:23'。这样的话匹配就会失败,不会将它检索出来。
解决办法是指示MySQL仅将给出的日期与列中的日期部分进行比较,而不是将给出的日期与整个列值进行比较。为此,必须使用Date()函数Date(order_date)指示MySQL仅提取列的日期部分。更可靠的SELECT语句为:

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

还有一种日期比较需要说明,如果想要检索20005年9月的所有订单。简单的相等测试肯定是不行的,因为它要具体匹配某一天。具体解决办法看下例:

MariaDB [course]> SELECT cust_id,order_num 
    -> FROM orders
    -> WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
+---------+-----------+
| cust_id | order_num |
+---------+-----------+
|   10001 |     20005 |
|   10003 |     20006 |
|   10004 |     20007 |
+---------+-----------+
3 rows in set (0.01 sec)

还有另外一种办法就是不用记住每个月有多少天,或者还需要考虑闰年2月的情况。
那就是使用Year()函数Month()函数

MariaDB [course]> SELECT cust_id,order_num 
    -> FROM orders
    -> WHERE Year(order_date) = '2005' AND Month(order_date) = '9';
+---------+-----------+
| cust_id | order_num |
+---------+-----------+
|   10001 |     20005 |
|   10003 |     20006 |
|   10004 |     20007 |
+---------+-----------+
3 rows in set (0.00 sec)

Year()是一个从日期返回年份的函数,Month()是一个从日期中返回月份的函数。
因此WHERE Year(order_date) = '2005' AND Month(order_date) = '9';返回日期为2005年9月的所有行。

2.3数值处理函数

数值处理函数仅处理数值数据,这些函数一般主要用于代数或几何运算,因此没有串或日期-时间处理函数使用的那么频繁。
在主要的DBMS中,这些函数是比较统一的。
在这里插入图片描述

MariaDB [course]> SELECT Sqrt(prod_price) AS sqrt_prod_price
    -> FROM products
    -> ORDER BY prod_name;
+--------------------+
| sqrt_prod_price    |
+--------------------+
| 2.4474476501040834 |
| 3.1606961258558215 |
|  3.871692136521188 |
| 3.1622776601683795 |
| 1.5811388300841898 |
|  3.605551275463989 |
|  1.849324200890693 |
|  5.916079783099616 |
|  7.416198487095663 |
|   2.99833287011299 |
| 7.0710678118654755 |
|  2.118962010041709 |
| 1.5811388300841898 |
| 3.1622776601683795 |
+--------------------+
14 rows in set (0.00 sec)

二、汇总数据函数

1、聚集函数

我们经常要汇总数据而不用把它们实际检索出来,为此MySQL提供了专门的函数。使用这些函数,MySQL查询可以用于检索数据,以便分析和报表生成,这种类型的检索例子有以下几种:

  • 确定表中的行数(或者满足某个条件或包含某个特定值的行)
  • 获得表中行组的和
  • 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值
    这些例子都要对表中的数据汇总,因此返回实际表数据是对时间和处理资源的以一种浪费。为了方便这种类型的检索,MySQL给出了5个聚集函数,这些函数能够进行上述罗列的检索。
    聚集函数: 运行在组之上,计算和返回单个值的函数。
函数 Academy
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和

1.1AVG()函数

AVG()通过对表中行数进行计数并计算特定列值之和,求得该列的平均值。AVG()可用来返回所有列的平均值,也可以用来返回特定列或行的平均值。
下面例子通过AVG()返回products表中所有产品的平均价格

MariaDB [course]> SELECT AVG(prod_price) AS avg_price
    -> FROM products;
+-----------+
| avg_price |
+-----------+
| 16.133571 |
+-----------+
1 row in set (0.00 sec)

AVG()也可以用来确定特定列或行的平均值,下面的例子返回特定供应商所提供产品的平均值:

MariaDB [course]> SELECT AVG(prod_price) AS avg_price
    -> FROM products
    -> WHERE vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 13.212857 |
+-----------+
1 row in set (0.00 sec)

这条SELECT语句与之前不同之处在于它包含了WHERE子句,次WHERE子句仅过滤出vend_id为1003的产品,因此avg_price中返回的值只是该供应商提供的产品平均价格。

只用于单个列:AVG()只能用来确定特定数值列的平均值,而且列名必须作为函数参数给出,为了获得多个列的平均值,必须使用多个AVG()函数。

AVG()函数忽略列值为NULL的值

1.2COUNT()函数

COUNT()函数进行计数,可利用COUNT()确定表中行的数目或符合特定条件的行的数目。
COUNT()函数有两种使用方式:

  • 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的空值还是非空值。
  • 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。

下面例子返回customers表中客户的总数:

MariaDB [course]> SELECT COUNT(*) AS count_num
    -> FROM customers;
+-----------+
| count_num |
+-----------+
|         5 |
+-----------+
1 row in set (0.00 sec)

在此例子中,利用COUNT(*)对所有行进行计数,不管行中各列有什么值,计数值在num_cust中返回。
下面的例子只对具有电子邮件地址的客户进行计数

MariaDB [course]> SELECT count(cust_email) AS count_num
    -> FROM customers;
+-----------+
| count_num |
+-----------+
|         3 |
+-----------+
1 row in set (0.00 sec)

具体表的结构是这样的:
DESC
可见使用COUNT(column)对cust_email列中具有值的行进行计数,忽略NULL值。

NULL值,如果指定列名,则指定列的值为空的行被COUNT()函数忽略。但如果使用的是COUNT(*)则不会忽略。

1.3MAX()函数

MAX()返回指定列中的最大值,MAX()要求指定列名,如下所示:

MariaDB [course]> SELECT MAX(prod_price) AS max_prices
    -> FROM products;
+------------+
| max_prices |
+------------+
|      55.00 |
+------------+
1 row in set (0.00 sec)

这里返回products表中最贵的物品的价格

对非数值数据使用MAX():虽然MAX()一般是用来找出最大的数值或日期值,但MySQL允许将它用来返回任意列的最大值,包括返回文本列中的最大值,在用于文本数据时,如果数据按相应的列排序,则MAX()返回最后一行。

-MAX()函数忽略列值为NULL的行。

1.4MIN()函数

MIN()功能正好与MAX()相反,返回指定列的最小值。与MAX()一样,MIN()也要求指定列名,如下例:

MariaDB [course]> SELECT MIN(prod_price) AS min_price
    -> FROM  products;
+-----------+
| min_price |
+-----------+
|      2.50 |
+-----------+
1 row in set (0.00 sec)

对非数值数据使用MIN():MIN()函数与MAX()函数一样,MySQL允许将它用来返回任意列中的最小值,包括返回文本列中的最小值,在用于文本数据时,如果数据按相应的列排序,则MIN()返回最前面的行。

MIN()函数忽略列值为NULL的行。

1.5SUM()函数

SUM()函数用来返回指定列值的和
orderitems表包含订单中实际的物品,每个物品有相应的数量(quantity),可如下检索所订购物品的总数(所有quantity值之和):

MariaDB [course]> SELECT SUM(quantity) AS items_ordered 
    -> FROM orderitems
    -> WHERE order_num=20005;
+---------------+
| items_ordered |
+---------------+
|            19 |
+---------------+
1 row in set (0.00 sec)

函数SUM(quantity)返回订单中所有物品数量之和,WHERE子句保证只统计某个物品订单中的物品
SUM()也可以用来合计计算值,在下面的例子中,合计每项物品的item_price*quantity,得出总的订单金额。

MariaDB [course]> SELECT SUM(item_price*quantity) AS total_price
    -> FROM orderitems
    -> WHERE order_num=20005;
+-------------+
| total_price |
+-------------+
|      149.87 |
+-------------+
1 row in set (0.00 sec)

函数SUM(item_price*quantity)返回订单中所有物品价钱之和,WHERE子句同样保证只统计某个物品订单的物品。

在多个列上进行计算,利用标准的算术操作符,所有聚集函数都可以用来执行多个 列上的计算。

SUM()函数忽略列值为NULL的行。

2、聚集不同值

以上的聚集函数都可以如下使用:

  • 对所有的行执行计算,指定ALL参数或不给参数(因为ALL是默认的参数)
  • 只包含不同的值,指定DISTINCT参数

ALL参数值为默认,ALL参数不需要指定,因为它是默认行为,如果不指定DISTINCT,则假定为ALL。

下例中使用AVG()函数返回特定供应商提供的产品的平均价格,,它与上面的SELECT语句相同,但使用了DISTINCT参数,因为平均值只考虑各个不同的价格:

MariaDB [course]> SELECT AVG(DISTINCT prod_price) AS  avg_price
    -> FROM products
    -> WHERE vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 15.998000 |
+-----------+
1 row in set (0.00 sec)

可以看出平均值比较之前没有使用DISTINCT的值较高,因为有多个物品具有相同的较低价格,排除它们提高了平均价格。

注意:如果指定列名,则DISTINCT之能用于COUNT()。DISTINCT不能用于COUNT(*),因此不允许使用COUNT(DISTINCT),否则将会产生错误,类似地,DISTINCT必须使用列名,不能用于计算或表达式。

3、组合聚集函数

目前为止地所有聚集函数例子都只涉及单个函数,但实际上 SELECT语句可根据需要包含多个聚集函数,看下例:

MariaDB [course]> SELECT COUNT(*) AS num_items, 
    -> MIN(prod_price) AS price_min,
    -> MAX(prod_price) AS price_max,
    -> AVG(prod_price) AS price_avg,
    -> SUM(prod_price) AS total_price
    -> FROM products;
+-----------+-----------+-----------+-----------+-------------+
| num_items | price_min | price_max | price_avg | total_price |
+-----------+-----------+-----------+-----------+-------------+
|        14 |      2.50 |     55.00 | 16.133571 |      225.87 |
+-----------+-----------+-----------+-----------+-------------+
1 row in set (0.00 sec)

这里用单条SELECT语句执行了5个聚集计算,返回5个值。

取别名,在指定别名以包含某个聚集函数的结果时,不应该使用表中实际列名,虽然这样做并非不合法,但使用唯一的列名会使SQL更易于理解和使用。

发布了114 篇原创文章 · 获赞 30 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_41476978/article/details/104200053