《MySQL必知必会》学习笔记-使用MySQL查询数据

《MySQL必知必会》学习笔记-使用MySQL查询数据

  • 查看
  • 检索数据
  • 排序检索数据
  • 过滤数据
  • 用通配符进行过滤
  • 用正则表达式进行搜索
  • 创建计算字段
  • 使用数据处理函数
  • 汇总数据
  • 分组数据
  • 子查询

查看

  • 选择数据库
输入 输出
USE crashcourse(数据库名); 不返回任何结果
  • 了解数据库和表
输入 输出
SHOW DATABASES; 返回可用数据库列表
SHOW TABLES; 返回当前选择的数据库内可用表的列表
SHOW COLUMNS FROM customers(表名) 返回表的字段,每个字段一行
DESCRIBE customers(表名) 同上
SHOW STATUS; 显示广泛的服务器状态信息
SHOW CREATE DATABASE; 显示创建特定数据库的MySQL语句
SHOW CREATE TABLE; 显示创建特定表的MySQL语句
SHOW GRANTS; 显示授予用户(所有用户或特定用户)的安全权限
SHOW ERRORS; 显示服务器错误消息
SHOW WARNINGS; 显示服务器警告消息
HELP SHOW 显示允许的SHOW语句

检索数据

  • 检索单列
    SELECT prod_name(列名) FROM products(表名);

如果没有明确排序查询结果,则返回的数据的顺序没有特殊意义。

  • 检索多列
    SELECT prod_id,prod_name,prod_price(列名) FROM products(表名);

SQL一般返回原始的、无格式的数据。数据的格式化是一个表示问题,而不是一个检索问题。表示一般在显示该数据的应用程序中规定。

  • 检索所有列
    SELECT * FROM products(表名);

检索不需要的列通常会降低检索和应用程序的性能。

  • 检索不同的行
    SELECT DISTINCT vend_id FROM products;
    SELECT DISTINCT vend_id, prod_price FROM products;

DINSTICT 关键字应用于所有列。

  • 限制结果
    SELECT prod_name FROM products LIMIT 5;
    SELECT prod_name FROM products LIMIT 3,4;
    SELECT prod_name FROM products LIMIT 4 OFFSET 3;

检索出来的第一行为行0。
LIMIT指定的行数为检索的最大行数,行数不够时将只返回它能返回的那么多行。
OFFSET指定开始返回的行。
后两句语句返回结果一样。

  • 使用完全限定的表名
    SELECT products.prod_name FROM crashcourse.products;

排序检索数据

  • 按单列排序
    SELECT prod_name FROM products ORDER BY prod_name;
  • 按多列排序
    SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name;

先按prod_price排序,当prod_price有多个行具有相同值时,再按prod_name排序。

  • 指定排序方向
    SELECT prod_id, prod_price,prod_name FROM products ORDER BY prod_price DESC,prod_name;

DESC只应用到直接位于其前面的列名。
升序ASC,但升序是默认的。
大小写如何排序,取决于数据库的设置。
ORDER BY 子句必须在FROM子句之后,LIMIT必须在ODER BY之后。

过滤数据

  • WHERE子句指定搜索条件(也称为过滤条件)
    SELECT prod_name, prod_price FROM products WHERE *prod_price = 2.50;

ORDER BY 子句应在WHERE子句之后。

数据也可以在应用层过滤。
让客户机应用(或开发语言)处理数据库的工作将会极大地影响应用的性能,并且使所创建的应用完全不具备可伸缩性。
如果在客户机上过滤数据,服务器不得不通过网络发送多余的数据,这将导致网络带宽的浪费。

  • WHERE子句操作符
操作符 说明
= 等于
<> 不等于
!= 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
BETWEEN 在指定的两个值之间

SELECT prod_name, prod_price FROM products WHERE prod_name = ‘fuse’;
SELECT prod_name, prod_price FROM products WHERE prod_price < 10;
SELECT vend_id, prod_name FROM products WHERE vend_id <> 1003;
SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN 5 AND 10;
SELECT prod_name, prod_price FROM products WHERE prod_price IS NULL;

MySQL在执行匹配时默认不区分大小写。
单引号用来限定字符串。
BETWEEN匹配范围中所有的值,包括指定的开始值和结束值。
因为NULL未知具有特殊的含义,数据库不知道它们是否匹配,所以在匹配过滤或不匹配过滤时不返回它们。

  • 组合WHERE子句(AND /OR)
    SELECT prod_id,prod_name,prod_price FROM products WHERE vend_id = 1003 AND prod_price <= 10;
    SELECT prod_id,prod_name,prod_price FROM products WHERE vend_id = 1003 OR vend_id = 1002;
    SELECT prod_id,prod_name,prod_price FROM products WHERE (vend_id = 1003 OR vend_id = 1002) AND prod_price >= 10 ;

使用圆括号明确地分组相应的操作符。

SELECT prod_id,prod_name,prod_price FROM products WHERE vend_id IN (1002,1003) ORDER BY prod_name;

使用长的合法选项清单时,IN操作符的语法更清楚且更直观。
使用IN时,计算的次序更容易管理。
IN操作符一般比OR操作符清单执行更快。
IN的最大优点是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句。

SELECT prod_id,prod_name,prod_price FROM products WHERE vend_id NOT IN (1002,1003)ORDER BY prod_name;

MySQL支持使用NOT对IN/BETWEEN/EXISTS子句取反。

用通配符进行过滤

利用通配符可以创建比较特定数据的搜索模式。
在搜索子句中使用通配符,必须使用LIKE操作符。

  • 通配符
  • 百分号 % (表示任何字符出现任意次数)
    SELECT prod_id, prod_name FROM products WHERE prod_name LIKE ‘jet%’;
    SELECT prod_id, prod_name FROM products WHERE prod_name LIKE ‘%anvil%’;

%能匹配0个字符。
%不能匹配NULL。

  • 下划线 _ (匹配单个字符)
    SELECT prod_id, prod_name FROM products WHERE prod_name LIKE ‘_ ton anvil’;

通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。
不要过度使用通配符。
在确实需要使用通配符时,除非绝对有必要,否则不能把它们用在搜索模式的开始处。
仔细注意通配符的位置。

用正则表达式进行搜索

正则表达式是用来匹配文本的特殊的串(字符集合)。
MySQL仅支持多数正则表达式实现的一个很小的子集。
关键字: REGEXP

LIKE与REGEXP的区别:
LIKE匹配整个列
REGEXP在列值内进行匹配

MySQL中的正则表达式匹配不区分大小写。为区分大小写,可使用BINARY关键字。

  • 基本字符匹配
    SELECT prod_name FROM products WHERE prod_name REGEXP ‘1000’;
    SELECT prod_name FROM products WHERE prod_name REGEXP ‘.000’;
  • OR匹配
    SELECT prod_name FROM products WHERE prod_name REGEXP ‘1000|2000’;
  • 匹配几个字符之一
    SELECT prod_name FROM products WHERE prod_name REGEXP ‘[123] Ton’;
    SELECT prod_name FROM products WHERE prod_name REGEXP ‘[1|2|3] Ton’;
    SELECT prod_name FROM products WHERE prod_name REGEXP ‘[^123] Ton’;

SELECT prod_name FROM products WHERE prod_name REGEXP ‘1|2|3 Ton’;与SELECT prod_name FROM products WHERE prod_name REGEXP ‘[1|2|3] Ton’;结果不一样,前者搜索的是’1’或’2’或‘3 Ton’。

  • 匹配范围
    mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[1-5] Ton’;
    ±-------------+
    | prod_name |
    ±-------------+
    | .5 ton anvil |
    | 1 ton anvil |
    | 2 ton anvil |
    ±-------------+
  • 匹配特殊字符(转义字符)
    mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘\\.’;
    ±-------------+
    | prod_name |
    ±-------------+
    | .5 ton anvil |
    ±-------------+
元字符 说明
\\f 换页
\\n 换行
\\r 回车
\\t 制表
\\v 纵向制表

为了匹配反斜杠(\)字符本省,需要使用\\\。

  • 匹配字符类
说明
[:alnum:] 任意字母和数字,同[a-zA-Z0-9]
[:alpha:] 任意字符,同[a-zA-Z]
[:blank:] 空格和制表,同\\t
[:cntrl:] ASCII控制字符,ASCII 0到31和127
[:digit:] 任意数字,同[0-9]
[:graph:] 与[:print:]相同,但不包括空格
[:lower:] 任意小写字母,同[a-z]
[:print:] 任意可打印字符
[:punct:] 既不在[:alnum:]又不在[:cntrl:]中的任意字符
[:space:] 包括空格在内的任意空白字符,同[\\f\\n\\r\\t\\v]
[:upper:] 任意大写字母,同[A-Z]
[:xdigit:] 任意十六进制数字,同[a-fA-F0-9]

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[:digit:]’;
±---------------+
| prod_name |
±---------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| JetPack 1000 |
| JetPack 2000 |
| TNT (1 stick) |
| TNT (5 sticks) |
±---------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[:blank:]’;
±---------------+
| prod_name |
±---------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
| Bird seed |
| JetPack 1000 |
| JetPack 2000 |
| Oil can |
| TNT (1 stick) |
| TNT (5 sticks) |
±---------------+

  • 匹配多个实例
元字符 说明(匹配该元字符前面的单个字符出现的次数)
* 0个或多个匹配
+ 1个或多个匹配,同{1,}
? 0个或1个匹配,同{0,1}
{n} 指定数目的匹配
{n,} 不少于指定数目的匹配
{n,m} 匹配数目的范围(m不超过255)

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘\\(* sticks\)’;
±---------------+
| prod_name |
±---------------+
| TNT (5 sticks) |
±---------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘\\(* sticks+\)’;
±---------------+
| prod_name |
±---------------+
| TNT (5 sticks) |
±---------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘\\([0-9] sticks?\)’;
±---------------+
| prod_name |
±---------------+
| TNT (1 stick) |
| TNT (5 sticks) |
±---------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[[:digit:]]{4}’;
±-------------+
| prod_name |
±-------------+
| JetPack 1000 |
| JetPack 2000 |
±-------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[0-1]{4}’;
±-------------+
| prod_name |
±-------------+
| JetPack 1000 |
±-------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[0-1]{3,4}’;
±-------------+
| prod_name |
±-------------+
| JetPack 1000 |
| JetPack 2000 |
±-------------+

  • 定位符
定位元字符 说明
^ 文本的开始
$ 文本的结尾
[[:<:]] 词的开始
[[:>:]] 词的结尾

mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘^[0-9\.]’;
±-------------+
| prod_name |
±-------------+
| .5 ton anvil |
| 1 ton anvil |
| 2 ton anvil |
±-------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[0]$’;
±-------------+
| prod_name |
±-------------+
| JetPack 1000 |
| JetPack 2000 |
±-------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[[j:<:]]’;
±-------------+
| prod_name |
±-------------+
| JetPack 1000 |
| JetPack 2000 |
±-------------+
mysql> SELECT prod_name FROM products WHERE prod_name REGEXP ‘[[k:>:]]’;
±---------------+
| prod_name |
±---------------+
| JetPack 1000 |
| JetPack 2000 |
| TNT (1 stick) |
| TNT (5 sticks) |
±---------------+

词的开始和结尾的语句不是太确定,搜索以k结尾的单词得到了“sticks”,正确用法还有待研究。

创建计算字段

直接从数据库中检索出转换、计算或格式化过的数据,计算字段并不实际存在于数据库表中。只有数据库知道SELECT语句中哪些列是实际的表列,哪些列是计算字段。

  • 拼接字段
    拼接(concatenate)——函数将值联结到一起构成单个值。
    使用函数:
  • Concat() 拼接串
  • RTrim() 去掉值右边的所有空格
  • LTrim() 去掉值左边的所有空格
  • Trim() 去掉串左右两边的空格
    mysql> SELECT Concat(RTrim(vend_name), ‘(’, RTrim(vend_country), ‘)’) FROM vendors ORDER BY vend_name;
    ±--------------------------------------------------------+
    | Concat(RTrim(vend_name), ‘(’, RTrim(vend_country), ‘)’) |
    ±--------------------------------------------------------+
    | ACME(USA) |
    | Anvils R Us(USA) |
    | Furball Inc.(USA) |
    | Jet Set(England) |
    | Jouets Et Ours(France) |
    | LT Supplies(USA) |
    ±--------------------------------------------------------+
  • 使用别名——关键字 AS
    mysql> SELECT Concat(RTrim(vend_name), ‘(’, RTrim(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) |
    ±-----------------------+
  • 执行算术计算——使用操作符 + - * /
    mysql> SELECT prod_id, quantity, item_price, quantity*item_price 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 |
    ±--------±---------±-----------±---------------+

使用数据处理函数

函数没有SQL的可移植性强。

  • 文本处理函数
函数 说明
Left()返回串左边的字符
Length() 返回串的长度
Locate() 找出串的一个子串
Lower() 将串转换为小写
LTrim() 去掉串左边的空格
Right() 返回串右边的字符
RTrim() 去掉串右边的空格
Soudex() 返回串的SOUNDEX值(将文本串转换为描述其语音表示的字母数字模式的算法)
SubString() 返回子串的字符
Upper() 将串转换为大写

mysql> SELECT Left(‘help_hello’,4);
±---------------------+
| left(‘help_hello’,4) |
±---------------------+
| help |
±---------------------+
mysql> SELECT Length(vend_name) FROM vendors;
±------------------+
| length(vend_name) |
±------------------+
| 11 |
| 11 |
| 4 |
| 12 |
| 7 |
| 14 |
±------------------+
mysql> SELECT vend_name, Locate(‘s’, vend_name) FROM vendors;
±---------------±-----------------------+
| vend_name | Locate(‘s’, vend_name) |
±---------------±-----------------------+
| Anvils R Us | 6 |
| LT Supplies | 4 |
| ACME | 0 |
| Furball Inc. | 0 |
| Jet Set | 5 |
| Jouets Et Ours | 6 |
±---------------±-----------------------+

Locate()返回的是子串第一次出现的位置,字符位置从1开始计算。

mysql> SELECT vend_name, SubString(vend_name,5) FROM vendors;
±---------------±-----------------------+
| vend_name | SubString(vend_name,5) |
±---------------±-----------------------+
| Anvils R Us | ls R Us |
| LT Supplies | upplies |
| ACME | |
| Furball Inc. | all Inc. |
| Jet Set | Set |
| Jouets Et Ours | ts Et Ours |
±---------------±-----------------------+
mysql> SELECT Lower(vend_name), Upper(vend_country) FROM vendors;
±-----------------±--------------------+
| Lower(vend_name) | Upper(vend_country) |
±-----------------±--------------------+
| anvils r us | USA |
| lt supplies | USA |
| acme | USA |
| furball inc. | USA |
| jet set | ENGLAND |
| jouets et ours | FRANCE |
±-----------------±--------------------+
mysql> SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact) = Soundex(‘Y. Lie’);
±------------±-------------+
| cust_name | cust_contact |
±------------±-------------+
| Coyote Inc. | Y Lee |
±------------±-------------+

  • 日期和时间处理函数
    一般,应用程序不使用用来存储日期和时间的格式,因此日期和时间函数总是被用来读取、统计和处理这些值。
函数 说明
AddData() 增加日期计算(天、周等)
AddTime() 增加时间计算(时、分等)
CurDate() 返回当前日期
CurTime() 返回当前时间
Data() 返回日期时间的日期部分
DataDiff() 计算两个日期只差
Data_Add() 高度灵活的日期计算函数
Date_Format()) 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分

mysql> select AddDate(‘2018-11-11’, INTERVAL 4 WEEK);
±---------------------------------------+
| AddDate(‘2018-11-11’, INTERVAL 4 WEEK) |
±---------------------------------------+
| 2018-12-09 |
±---------------------------------------+
mysql> select AddDate(‘2018-11-11’, INTERVAL 32 DAY);
±---------------------------------------+
| AddDate(‘2018-11-11’, INTERVAL 32 DAY) |
±---------------------------------------+
| 2018-12-13 |
±---------------------------------------+
mysql> select AddDate(‘2018-11-11’, INTERVAL 3 MONTH);
±----------------------------------------+
| AddDate(‘2018-11-11’, INTERVAL 3 MONTH) |
±----------------------------------------+
| 2019-02-11 |
±----------------------------------------+

日期格式yyyy-mm-dd

mysql> SELECT AddTime(‘23:59:59.999999’, ‘1:1:1.000002’);
±-------------------------------------------+
| AddTime(‘23:59:59.999999’, ‘1:1:1.000002’) |
±-------------------------------------------+
| 25:01:01.000001 |
±-------------------------------------------+
mysql> SELECT AddTime(‘01:59:59.999999’, ‘1:1:1.000002’);
±-------------------------------------------+
| AddTime(‘01:59:59.999999’, ‘1:1:1.000002’) |
±-------------------------------------------+
| 03:01:01.000001 |
±-------------------------------------------+

时间格式hh:mm:ss.ffffff
下面的计算结果超出了24小时:
mysql> SELECT AddTime(‘23:59:59.999999’, ‘1:1:1.000002’);
±-------------------------------------------+
| AddTime(‘23:59:59.999999’, ‘1:1:1.000002’) |
±-------------------------------------------+
| 25:01:01.000001 |
±-------------------------------------------+

mysql> SELECT CurDate();
±-----------+
| CurDate() |
±-----------+
| 2018-11-08 |
±-----------+
mysql> SELECT CurTime();
±----------+
| CurTime() |
±----------+
| 11:11:10 |
±----------+
mysql> SELECT Date(Now());
±------------+
| Date(Now()) |
±------------+
| 2018-11-08 |
±------------+
mysql> SELECT Day(CurDate());
±---------------+
| Day(CurDate()) |
±---------------+
| 8 |
±---------------+
mysql> SELECT Week(CurDate());
±----------------+
| Week(CurDate()) |
±----------------+
| 44 |
±----------------+
mysql> SELECT DayOfWeek(CurDate());
±---------------------+
| DayOfWeek(CurDate()) |
±---------------------+
| 5 |
±---------------------+
mysql> SELECT Month(CurDate());
±-----------------+
| Month(CurDate()) |
±-----------------+
| 11 |
±-----------------+
mysql> SELECT Year(CurDate());
±----------------+
| Year(CurDate()) |
±----------------+
| 2018 |
±----------------+
mysql> SELECT Time(Now());
±------------+
| Time(Now()) |
±------------+
| 11:15:41 |
±------------+
mysql> SELECT Second(CurTime());
±------------------+
| Second(CurTime()) |
±------------------+
| 41 |
±------------------+
mysql> SELECT Minute(CurTime());
±------------------+
| Minute(CurTime()) |
±------------------+
| 17 |
±------------------+
mysql> SELECT Hour(CurTime());
±----------------+
| Hour(CurTime()) |
±----------------+
| 11 |
±----------------+
mysql> SELECT DateDiff(CurDate(), ‘2017-11-11’);
±----------------------------------+
| DateDiff(CurDate(), ‘2017-11-11’) |
±----------------------------------+
| 362 |
±----------------------------------+
mysql> SELECT DateDiff(CurDate(), ‘2020-11-11’);
±----------------------------------+
| DateDiff(CurDate(), ‘2020-11-11’) |
±----------------------------------+
| -734 |
±----------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1’ WEEK);
±--------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1’ WEEK) |
±--------------------------------------------------+
| 2012-01-07 23:59:59 |
±--------------------------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1’ YEAR);
±--------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1’ YEAR) |
±--------------------------------------------------+
| 2012-12-31 23:59:59 |
±--------------------------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1’ SECOND);
±----------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1’ SECOND) |
±----------------------------------------------------+
| 2012-01-01 00:00:00 |
±----------------------------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59.999999’,INTERVAL ‘1’ MICROSECOND);
±----------------------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59.999999’,INTERVAL ‘1’ MICROSECOND) |
±----------------------------------------------------------------+
| 2012-01-01 00:00:00 |
±----------------------------------------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1 00:00:01’ DAY_SECOND);
±-----------------------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1 00:00:01’ DAY_SECOND) |
±-----------------------------------------------------------------+
| 2012-01-02 00:00:00 |
±-----------------------------------------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1.000002’ SECOND_MICROSECOND);
±-----------------------------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59’,INTERVAL ‘1.000002’ SECOND_MICROSECOND) |
±-----------------------------------------------------------------------+
| 2012-01-01 00:00:00.000002 |
±-----------------------------------------------------------------------+
mysql> SELECT Date_Add(‘2011-12-31 23:59:59.000000’,INTERVAL ‘11 1:1:1:000001’ DAY_MICROSECOND);
±----------------------------------------------------------------------------------+
| Date_Add(‘2011-12-31 23:59:59.000000’,INTERVAL ‘11 1:1:1:000001’ DAY_MICROSECOND) |
±----------------------------------------------------------------------------------+
| 2012-01-12 01:01:00.000001 |
±----------------------------------------------------------------------------------+
mysql> SELECT Date_Format(Now(), ‘%d %M %Y %W %H:%I:%s’);
±-------------------------------------------+
| Date_Format(Now(), ‘%d %M %Y %W %H:%I:%s’) |
±-------------------------------------------+
| 08 November 2018 Thursday 11:11:38 |
±-------------------------------------------+
mysql> SELECT Date_Format(Now(), ‘%d %M %Y %H:%i:%s’);
±----------------------------------------+
| Date_Format(Now(), ‘%d %M %Y %H:%i:%s’) |
±----------------------------------------+
| 08 November 2018 11:33:56 |
±----------------------------------------+

更多的日期、时间串的格式见
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format

mysql> 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 |
±--------±----------+
mysql> 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 |
±--------±----------+

  • 数值处理函数
    主要用于代数、三角或几何运算的函数。

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

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

三角函数的输入参数为弧度制。

mysql> SELECT Cos(PI());
±----------+
| Cos(PI()) |
±----------+
| -1 |
±----------+
mysql> SELECT Sin(PI()/2);
±------------+
| Sin(PI()/2) |
±------------+
| 1 |
±------------+
mysql> SELECT Mod(23,3);
±----------+
| Mod(23,3) |
±----------+
| 2 |
±----------+
mysql> SELECT Sqrt(16);
±---------+
| Sqrt(16) |
±---------+
| 4 |
±---------+
mysql> SELECT Tan(PI()/4);
±-------------------+
| Tan(PI()/4) |
±-------------------+
| 0.9999999999999999 |
±-------------------+

汇总数据

  • 聚集函数(aggregate function)
    对表中数据进行汇总而不是把它们实际检索出来,包括:

  • 确定表中行数(或者满足某个条件或包含某个特定值的行数);

  • 获得表中行组的和;

  • 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。

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

mysql> SELECT AVG(prod_price) AS avg_price FROM products WHERE vend_id = 1003;
±----------+
| avg_price |
±----------+
| 13.212857 |
±----------+

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

mysql> SELECT COUNT(*) AS num_cust FROM customers;
±---------+
| num_cust |
±---------+
| 5 |
±---------+
mysql> SELECT COUNT(cust_email) AS num_emial FROM customers;
±----------+
| num_emial |
±----------+
| 3 |
±----------+

如果指定列名,则值为NULL的行被忽略。
如果参数为*,则不忽略NULL值。

mysql> SELECT MAX(prod_price) AS max_price FROM products;
±----------+
| max_price |
±----------+
| 55.00 |
±----------+
mysql> SELECT MIN(prod_price) AS max_price FROM products;
±----------+
| max_price |
±----------+
| 2.50 |
±----------+

MAX(),MIN()一般用来找出最大/最小的数值或日期值。
当MAX(),MIN()用于文本数据时,如果数据按相应的列排序,则MAX()返回最后一行,MIN()返回最前面一行。
MAX(),MIN()忽略NULL值。

mysql> SELECT SUM(item_price*quantity) AS total_price FROM orderitems WHERE order_num = 20005;
±------------+
| total_price |
±------------+
| 149.87 |
±------------+

SUM()忽略NULL值。

  • 聚集不同值
  • 对所有的行执行计算,指定ALL参数或不给参数;
  • 只包含不同的值,指定DINSTINCT参数。

mysql> SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id = 1003;
±----------+
| avg_price |
±----------+
| 15.998000 |
±----------+
mysql> SELECT AVG(prod_price) AS avg_price FROM products WHERE vend_id = 1003;
±----------+
| avg_price |
±----------+
| 13.212857 |
±----------+

DISTINCT必须使用列名,不能用于计算或表达式。

  • 组合聚集函数
    将多个聚集函数用于单条SELECT语句。
    mysql> SELECT COUNT(*) AS num_items,
    -> MIN(prod_price) AS min_price,
    -> MAX(prod_price) AS max_price,
    -> AVG(prod_price) AS avg_price
    -> FROM products;
    ±----------±----------±----------±----------+
    | num_items | min_price | max_price | avg_price |
    ±----------±----------±----------±----------+
    | 14 | 2.50 | 55.00 | 16.133571 |
    ±----------±----------±----------±----------+

分组数据

分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。

  • 创建分组
    mysql> SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id;
    ±--------±----------+
    | vend_id | num_prods |
    ±--------±----------+
    | 1001 | 3 |
    | 1002 | 2 |
    | 1003 | 7 |
    | 1005 | 2 |
    ±--------±----------+

GROUP BY可以包含任意数目的列,这使得能对分组进行嵌套,为数据分组提供更细致的控制。
如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。(在建立分组时,指定的所有列都一起计算)
GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。
如果分组列中有NULL值,则NULL作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
GRUOP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。

使用关键字WITH ROLLUP可以得到每个分组以及每个分组汇总级别(针对每个分组)的值。
mysql> SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id WITH ROLLUP;
±--------±----------+
| vend_id | num_prods |
±--------±----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
| NULL | 14 |
±--------±----------+

  • 过滤分组
    WHERE过滤的是行,使用HAVING过滤分组。

HAVING支持所有WHERE操作符。

mysql> SELECT cust_id, COUNT() AS orders FROM orders GROUP BY cust_id HAVING COUNT() >= 2;
±--------±-------+
| cust_id | orders |
±--------±-------+
| 10001 | 2 |
±--------±-------+

WHERE在分组前过滤,HAVING在分组后进行过滤。
WHERE排除的行不包括在分组中。

mysql> SELECT vend_id, COUNT() AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT() >= 2;
±--------±----------+
| vend_id | num_prods |
±--------±----------+
| 1003 | 4 |
| 1005 | 2 |
±--------±----------+

mysql> SELECT vend_id, COUNT() AS num_prods FROM products GROUP BY vend_id HAVING COUNT() >= 2;
±--------±----------+
| vend_id | num_prods |
±--------±----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
±--------±----------+

  • 分组和排序
    一般在使用GROUP BY子句时,应该也给出ORDER BY 子句,这是保证数据正确排序的唯一方法。千万不要依赖GROUP BY排序数据。
    mysql> SELECT order_num, SUM(quantityitem_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantityitem_price) >= 50 ORDER BY ordertotal;
    ±----------±-----------+
    | order_num | ordertotal |
    ±----------±-----------+
    | 20006 | 55.00 |
    | 20008 | 125.00 |
    | 20005 | 149.87 |
    | 20007 | 1000.00 |
    ±----------±-----------+

顺序
SELECT – FROM – WHERE – GROUP BY – HAVING – ORDER BY – LIMIT


子查询

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

  • 利用子查询进行过滤
    mysql> SELECT cust_name, cust_contact
    -> FROM customers
    -> WHERE cust_id IN (SELECT cust_id FROM orders
    -> WHERE order_num in (SELECT order_num FROM orderitems
    -> WHERE prod_id = ‘TNT2’));
    ±---------------±-------------+
    | cust_name | cust_contact |
    ±---------------±-------------+
    | Coyote Inc. | Y Lee |
    | Yosemite Place | Y Sam |
    ±---------------±-------------+

对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。
在WHERE子句中使用子查询,应该保证SELECT语句具有与WHERE子句相同数目的列。
子查询一般与IN操作符结合使用,也可以用于测试 等于= 不等于<> 等。

  • 作为计算字段使用子查询
    mysql> SELECT cust_name, cust_state,
    -> (SELECT COUNT(*) FROM orders
    -> WHERE orders.cust_id = customers.cust_id) AS orders
    -> FROM customers
    -> ORDER BY cust_name;
    ±---------------±-----------±-------+
    | cust_name | cust_state | orders |
    ±---------------±-----------±-------+
    | Coyote Inc. | MI | 2 |
    | E Fudd | IL | 1 |
    | Mouse House | OH | 0 |
    | Wascals | IN | 1 |
    | Yosemite Place | AZ | 1 |
    ±---------------±-----------±-------+

你可能感兴趣的:(MySql学习)