MySQL必知必会读书笔记9-14章

MySQL必知必会读书笔记9-14章_第1张图片
MySQL必知必会读书笔记9-14章_第2张图片

第九章 用正则表达式进行搜索

正则表达式:匹配文本,将一个模式(正则表达式)与一个文本串进行比较。

MySQL 仅支持多数正则表达式实现的一个很小的子集。MySQL使用WHERE子句对正则表达式提供了初步的支持,允许你通过指定正则表达式来过滤SELECT检索出来的数据。

基本字符匹配

检索列prod_name包含文本1000的所有行

mysql> SELECT * FROM products WHERE prod_name REGEXP '1000';
+---------+---------+--------------+------------+---------------------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc                             |
+---------+---------+--------------+------------+---------------------------------------+
| JP1000  |    1005 | JetPack 1000 |      35.00 | JetPack 1000, intended for single use |
+---------+---------+--------------+------------+---------------------------------------+
1 row in set (0.08 sec)

这条语句和过去我们使用LIKE很相似,但是使用LIKE的结果却为空,从这也看出正则表达式匹配和使用LIKE匹配的差别。

mysql> SELECT * FROM products WHERE prod_name LIKE '1000';
Empty set (0.00 sec)

LIKE:匹配整个列,如果被匹配的文本在列值中出现,LIKE将不会找到它,相应的行也不会被返回。(除非使用通配符)
REGEXP:在列值中匹配,如果被匹配的文本在列值中出现,REGEXP将会找到它,相应的行将被返回。当然REGEXP也可以用来匹配整个列值,使用后面介绍的^$ 定位符。

MySQL正则表达式匹配不区分大小写,为了使其区分大小写,可以使用REGEXP BINARY。

mysql> SELECT * FROM products WHERE prod_name REGEXP '.000';
+---------+---------+--------------+------------+---------------------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc                             |
+---------+---------+--------------+------------+---------------------------------------+
| JP1000  |    1005 | JetPack 1000 |      35.00 | JetPack 1000, intended for single use |
| JP2000  |    1005 | JetPack 2000 |      55.00 | JetPack 2000, multi-use               |
+---------+---------+--------------+------------+---------------------------------------+
2 rows in set (0.00 sec)

. 是正则表达式中的一个特殊字符,它表示匹配任一一个字符。

进行OR匹配

为了检索两个串之一,使用|

mysql> SELECT * FROM products WHERE prod_name REGEXP '1000 | 2000';
+---------+---------+--------------+------------+-------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc               |
+---------+---------+--------------+------------+-------------------------+
| JP2000  |    1005 | JetPack 2000 |      55.00 | JetPack 2000, multi-use |
+---------+---------+--------------+------------+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM products WHERE prod_name REGEXP '1000|2000';
+---------+---------+--------------+------------+---------------------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc                             |
+---------+---------+--------------+------------+---------------------------------------+
| JP1000  |    1005 | JetPack 1000 |      35.00 | JetPack 1000, intended for single use |
| JP2000  |    1005 | JetPack 2000 |      55.00 | JetPack 2000, multi-use               |
+---------+---------+--------------+------------+---------------------------------------+
2 rows in set (0.00 sec)

| 为正则表达式中OR操作符
注意:1000 | 2000:匹配的是1000空格空格20000

匹配几个字符之一

mysql> SELECT * FROM products WHERE prod_name REGEXP '[123] Ton';
+---------+---------+-------------+------------+----------------------------------------------------------------+
| prod_id | vend_id | prod_name   | prod_price | prod_desc                                                      |
+---------+---------+-------------+------------+----------------------------------------------------------------+
| ANV02   |    1001 | 1 ton anvil |       9.99 | 1 ton anvil, black, complete with handy hook and carrying case |
| ANV03   |    1001 | 2 ton anvil |      14.99 | 2 ton anvil, black, complete with handy hook and carrying case |
+---------+---------+-------------+------------+----------------------------------------------------------------+
2 rows in set (0.00 sec)

[123]定义一组字符,它的意思是匹配1或2或3。
[123] Ton等价于:[1|2|3] Ton
[^123]:匹配除这些字符外的任何东西

匹配范围

mysql> SELECT * FROM products WHERE prod_name REGEXP '[1-5] Ton';
+---------+---------+--------------+------------+----------------------------------------------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc                                                      |
+---------+---------+--------------+------------+----------------------------------------------------------------+
| ANV01   |    1001 | .5 ton anvil |       5.99 | .5 ton anvil, black, complete with handy hook                  |
| ANV02   |    1001 | 1 ton anvil  |       9.99 | 1 ton anvil, black, complete with handy hook and carrying case |
| ANV03   |    1001 | 2 ton anvil  |      14.99 | 2 ton anvil, black, complete with handy hook and carrying case |
+---------+---------+--------------+------------+----------------------------------------------------------------+
3 rows in set (0.00 sec)

[1-5] Ton:等价于[12345] Ton

匹配特殊字符

也就是去匹配正则表达式中的特殊字符。使用\\转译
如查找.则需要REGEXP ‘\.’

匹配字符类

说明
[:alnum:] 任意字母和数字(同[a-zA-Z0-9])
[:alpha:] 任意字符(同[a-zA-Z])
[:blank:] 空格和制表(同[\t])
[:digit:] 任意数字(同[0-9])

匹配多个实例

说明
* 0个或多个匹配
+ 1个或多个匹配
? 0个或1个匹配
{n} n个匹配
{n,} >=n个匹配
{n,m} >=n <= m个匹配
mysql> SELECT * FROM products WHERE prod_name REGEXP '\\([0-9] sticks?\\)';
+---------+---------+----------------+------------+-----------------------------+
| prod_id | vend_id | prod_name      | prod_price | prod_desc                   |
+---------+---------+----------------+------------+-----------------------------+
| TNT1    |    1003 | TNT (1 stick)  |       2.50 | TNT, red, single stick      |
| TNT2    |    1003 | TNT (5 sticks) |      10.00 | TNT, red, pack of 10 sticks |
+---------+---------+----------------+------------+-----------------------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM products WHERE prod_name REGEXP '[[:digit:]]{4}';
+---------+---------+--------------+------------+---------------------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc                             |
+---------+---------+--------------+------------+---------------------------------------+
| JP1000  |    1005 | JetPack 1000 |      35.00 | JetPack 1000, intended for single use |
| JP2000  |    1005 | JetPack 2000 |      55.00 | JetPack 2000, multi-use               |
+---------+---------+--------------+------------+---------------------------------------+
2 rows in set (0.00 sec)

定位符

说明
^ 文本多的开始
$ 文本的结尾
[[:<:]] 词的开始
[[:>:]] 词的结尾
mysql> SELECT * FROM products WHERE prod_name REGEXP '^[0-9\\.]';
+---------+---------+--------------+------------+----------------------------------------------------------------+
| prod_id | vend_id | prod_name    | prod_price | prod_desc                                                      |
+---------+---------+--------------+------------+----------------------------------------------------------------+
| ANV01   |    1001 | .5 ton anvil |       5.99 | .5 ton anvil, black, complete with handy hook                  |
| ANV02   |    1001 | 1 ton anvil  |       9.99 | 1 ton anvil, black, complete with handy hook and carrying case |
| ANV03   |    1001 | 2 ton anvil  |      14.99 | 2 ton anvil, black, complete with handy hook and carrying case |
+---------+---------+--------------+------------+----------------------------------------------------------------+
3 rows in set (0.00 sec)

以上查询以数字或者小数点开始的数据。

可以使用带文本串的REGEXP来测试表达式
例如:SELECT 'hello' REGEXP '[0-9]';
匹配返回1,不匹配返回0。


第十章 创建计算字段

计算字段不是实际存在于数据库表中的,而是通过在运行时在SELECT语句创建的。

拼接字段:将值联结到一起构成单个值。

mysql> SELECT Concat(vend_name, ' (', vend_country, ')') FROM vendors ORDER BY vend_name;
+--------------------------------------------+
| Concat(vend_name, ' (', vend_country, ')') |
+--------------------------------------------+
| ACME (USA)                                 |
| Anvils R Us (USA)                          |
| Furball Inc. (USA)                         |
| Jet Set (England)                          |
| Jouets Et Ours (France)                    |
| LT Supplies (USA)                          |
+--------------------------------------------+
6 rows in set (0.00 sec)

上述输出的列是没有名字的,要想在客户机应用如(MyBatis)中引用,需要设置别名。

mysql> SELECT Concat(vend_name, ' (', vend_country, ')') AS vend_title FROM vendors ORDER BY vend_name;
+-------------------------+
| vend_title              |
+-------------------------+
| ACME (USA)              |
| Anvils R Us (USA)       |
| Furball Inc. (USA)      |
| Jet Set (England)       |
| Jouets Et Ours (France) |
| LT Supplies (USA)       |
+-------------------------+
6 rows in set (0.00 sec)

执行算术计算

mysql> SELECT prod_id, quantity, item_price FROM orderitems WHERE order_num = 20005;
+---------+----------+------------+
| prod_id | quantity | item_price |
+---------+----------+------------+
| ANV01   |       10 |       5.99 |
| ANV02   |        3 |       9.99 |
| TNT2    |        5 |      10.00 |
| FB      |        1 |      10.00 |
+---------+----------+------------+
4 rows in set (0.06 sec)

mysql> SELECT prod_id, quantity, item_price, item_price * quantity AS expanded_price FROM orderitems WHERE order_num = 20005;
+---------+----------+------------+----------------+
| prod_id | quantity | item_price | expanded_price |
+---------+----------+------------+----------------+
| ANV01   |       10 |       5.99 |          59.90 |
| ANV02   |        3 |       9.99 |          29.97 |
| TNT2    |        5 |      10.00 |          50.00 |
| FB      |        1 |      10.00 |          10.00 |
+---------+----------+------------+----------------+
4 rows in set (0.00 sec)

第十一章 使用数据处理函数

11.1函数

函数没有SQL的可移植性强,所以在使用时应该保证做好代码注释。

11.2 使用函数

11.2.1 文本处理函数

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

使用:

SELECT prod_id, Left(prod_id, 2) FROM products;
SELECT prod_id, Right(prod_id, 2) FROM products;
SELECT Length(prod_id) FROM products;
SELECT prod_name, Lower(prod_name), Upper(prod_name) FROM products;
SELECT prod_name, SubString(prod_name, 1, 2) FROM products;
SELECT LOCATE('ton', prod_name) FROM products;

11.2.2 日期和时间处理函数

函数 说明
AddDate() 增加一个日期(天、周等)
AddTime() 增加一个时间(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Date() 返回日期时间的日期部分
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分

mysql> SELECT now(), Date(now()), Time(now());
+---------------------+-------------+-------------+
| now()               | Date(now()) | Time(now()) |
+---------------------+-------------+-------------+
| 2017-07-09 12:41:39 | 2017-07-09  | 12:41:39    |
+---------------------+-------------+-------------+
1 row in set (0.01 sec)

日期的格式为:yyyy-mm-dd,如2017-07-09。这是首选的日期根式。

MySQL中datetime类型存储日期及时间。可以使用Date()函数提取需要的日期。

mysql> SELECT * FROM orders WHERE Date(order_date) = '2005-09-01';
+-----------+---------------------+---------+
| order_num | order_date          | cust_id |
+-----------+---------------------+---------+
|     20005 | 2005-09-01 00:00:00 |   10001 |
+-----------+---------------------+---------+
1 row in set (0.00 sec)

如何检索出形如2005年9月份的所有订单?

mysql> SELECT * FROM orders WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
+-----------+---------------------+---------+
| order_num | order_date          | cust_id |
+-----------+---------------------+---------+
|     20005 | 2005-09-01 00:00:00 |   10001 |
|     20006 | 2005-09-12 00:00:00 |   10003 |
|     20007 | 2005-09-30 00:00:00 |   10004 |
+-----------+---------------------+---------+
3 rows in set (0.00 sec)

但是以上方法需要写出每个月份有多少天,以及需要关心闰年。

mysql> SELECT * FROM orders WHERE Year(order_date) = 2005 AND Month(order_date) = 9;
+-----------+---------------------+---------+
| order_num | order_date          | cust_id |
+-----------+---------------------+---------+
|     20005 | 2005-09-01 00:00:00 |   10001 |
|     20006 | 2005-09-12 00:00:00 |   10003 |
|     20007 | 2005-09-30 00:00:00 |   10004 |
+-----------+---------------------+---------+
3 rows in set (0.00 sec)

11.2.3 数值处理函数

数值处理函数仅处理数值数据。

函数 说明
Abs() 返回一个数的绝对值
Cos() 返回一个角度的余弦
Exp() 返回一个数的指数值
Mod() 返回除操作的余数
Pi() 返回圆周率
Rand() 返回一个随机数
Sin() 返回一个角度的正弦
Sqrt() 返回一个数的平方根
Tan() 返回一个角度的正切

第十二章 汇总数据

12.1 聚集函数

我们经常需要汇总数据而不是把数据实际检索出来,为此MySQL提供了聚集函数。

  • 确定表中的行数。
  • 获得表中行组的和。
  • 找出表列的最大值、最小值和平均值。

以上都是聚集函数的使用场合。

聚集函数:运行在行组上,计算和返回单个值的函数。

函数 说明
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列子和

12.1.1 AVG()函数

通过对表中行数计数并计算特定列值之和,求得该列的平均值。
返回所有列的平均值:

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

返回特定列或行的平均值:

mysql> SELECT AVG(prod_price) AS avg_price FROM products WHERE vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 13.212857 |
+-----------+
1 row in set (0.06 sec)

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

12.1.2 COUNT()函数

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

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

返回customer表中客户的总数:

mysql> SELECT COUNT(*) AS num_cust FROM customers;
+----------+
| num_cust |
+----------+
|        5 |
+----------+
1 row in set (0.07 sec)

返回具有电子邮件地址的客户计数:

mysql> SELECT COUNT(cust_email) AS num_cust FROM customers;
+----------+
| num_cust |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT * FROM customers;
+---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+
| cust_id | cust_name      | cust_address        | cust_city | cust_state | cust_zip | cust_country | cust_contact | cust_email          |
+---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+
|   10001 | Coyote Inc.    | 200 Maple Lane      | Detroit   | MI         | 44444    | USA          | Y Lee        | [email protected]     |
|   10002 | Mouse House    | 333 Fromage Lane    | Columbus  | OH         | 43333    | USA          | Jerry Mouse  | NULL                |
|   10003 | Wascals        | 1 Sunny Place       | Muncie    | IN         | 42222    | USA          | Jim Jones    | [email protected] |
|   10004 | Yosemite Place | 829 Riverside Drive | Phoenix   | AZ         | 88888    | USA          | Y Sam        | [email protected]    |
|   10005 | E Fudd         | 4545 53rd Street    | Chicago   | IL         | 54545    | USA          | E Fudd       | NULL                |
+---------+----------------+---------------------+-----------+------------+----------+--------------+--------------+---------------------+
5 rows in set (0.00 sec)

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

12.1.3 MAX()函数

返回指定列中的最大值。必须指定列名。

mysql> SELECT MAX(prod_price) AS max_price FROM products;
+-----------+
| max_price |
+-----------+
|     55.00 |
+-----------+
1 row in set (0.04 sec)

等价于:

mysql> SELECT prod_price AS 'max(prod_price)' FROM products ORDER BY prod_price DESC LIMIT 1;
+-----------------+
| max(prod_price) |
+-----------------+
|           55.00 |
+-----------------+
1 row in set (0.00 sec)

12.1.4 MIN()函数

返回指定列的最小值。必须指定列名。

mysql> SELECT MIN(prod_price) AS max_price FROM products;
+-----------+
| max_price |
+-----------+
|      2.50 |
+-----------+
1 row in set (0.00 sec)

MAX()与MIN()函数都忽略列值为NULL的行。两个函数对非数值数据也适用。

12.1.5 SUM()函数

返回指定列值的和。

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

SUM()函数也可以用来合计计算值。

mysql> 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()函数忽略列值为NULL的行。

12.2 聚集不同值

针对MySQL 5及后期版本
只包含不同的值,指定DISTINCT参数。

mysql> SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id = 1003;
+-----------+
| avg_price |
+-----------+
| 15.998000 |
+-----------+
1 row in set (0.05 sec)

12.3 组合聚集函数

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

第十三章 分组数据

第十四章 使用子查询

子查询:嵌套在其他查询中的查询。

MySQL必知必会读书笔记9-14章_第3张图片
查询订购物品TNT2的所有客户
步骤:
- 检索包含物品TNT2 的所有订单的编号。

SELECT order_num FROM orderitems WHERE prod_id = 'TNT2';
  • 检索具有前一步骤列出的订单编号的所有客户的ID。
SELECT cust_id FROM orders WHERE order_num IN (20005, 20007);
  • 检索前一步骤返回的所有客户ID的客户信息。
SELECT * FROM customers WHERE cust_id IN (10001, 10004);

使用子查询就是把上述三个查询合成一条语句。

SELECT *
FROM customers
WHERE cust_id IN (SELECT cust_id
                  FROM orders
                  WHERE order_num IN (SELECT order_num
                                      FROM orderitems
                                      WHERE prod_id = 'TNT2'));

在SELECT语句中,子查询总是从内向外处理。

检索customers表中每个客户的订单总数。
MySQL必知必会读书笔记9-14章_第4张图片

步骤:
从customers表中检索客户列表。
对于检索出来的每个客户,统计其在orders表中的订单数目。

SELECT
  cust_id,
  cust_name,
  (SELECT count(*)
   FROM orders
   WHERE cust_id = customers.cust_id)
    AS orders
FROM
  customers;

你可能感兴趣的:(Database,Linux)