输入 | 输出 |
---|---|
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语句 |
如果没有明确排序查询结果,则返回的数据的顺序没有特殊意义。
SQL一般返回原始的、无格式的数据。数据的格式化是一个表示问题,而不是一个检索问题。表示一般在显示该数据的应用程序中规定。
检索不需要的列通常会降低检索和应用程序的性能。
DINSTICT 关键字应用于所有列。
检索出来的第一行为行0。
LIMIT指定的行数为检索的最大行数,行数不够时将只返回它能返回的那么多行。
OFFSET指定开始返回的行。
后两句语句返回结果一样。
先按prod_price排序,当prod_price有多个行具有相同值时,再按prod_name排序。
DESC只应用到直接位于其前面的列名。
升序ASC,但升序是默认的。
大小写如何排序,取决于数据库的设置。
ORDER BY 子句必须在FROM子句之后,LIMIT必须在ODER BY之后。
ORDER BY 子句应在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未知具有特殊的含义,数据库不知道它们是否匹配,所以在匹配过滤或不匹配过滤时不返回它们。
使用圆括号明确地分组相应的操作符。
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操作符。
%能匹配0个字符。
%不能匹配NULL。
通配符搜索的处理一般要比前面讨论的其他搜索所花时间更长。
不要过度使用通配符。
在确实需要使用通配符时,除非绝对有必要,否则不能把它们用在搜索模式的开始处。
仔细注意通配符的位置。
正则表达式是用来匹配文本的特殊的串(字符集合)。
MySQL仅支持多数正则表达式实现的一个很小的子集。
关键字: REGEXP
LIKE与REGEXP的区别:
LIKE匹配整个列
REGEXP在列值内进行匹配
MySQL中的正则表达式匹配不区分大小写。为区分大小写,可使用BINARY关键字。
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’。
元字符 | 说明 |
---|---|
\\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语句中哪些列是实际的表列,哪些列是计算字段。
函数没有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值。
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必须使用列名,不能用于计算或表达式。
分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。
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 |
±--------±----------+
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 |
±--------±----------+
顺序
SELECT – FROM – WHERE – GROUP BY – HAVING – ORDER BY – LIMIT
子查询:嵌套在其他查询中的查询。
对于能嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。
在WHERE子句中使用子查询,应该保证SELECT语句具有与WHERE子句相同数目的列。
子查询一般与IN操作符结合使用,也可以用于测试 等于= 不等于<> 等。