本文将详细介绍 SQL 中的四种子句 WHERE / ORDER BY / GROUP BY / HAVING,以及基本运算 / 特殊条件表达式 / 函数 / 聚集函数。

数据过滤 WHERE

基本格式

SELECT 语句可以使用 WHERE 进行数据过滤。格式为:

1
{SELECT 语句} WHERE {条件表达式};
1
SELECT * FROM MovieStar WHERE birthDATE >= "19700101";
1
2
3
4
5
6
7
8
+--------------+-------------+--------+------------+
| name | address | gender | birthDate |
+--------------+-------------+--------+------------+
| Alec Baldwin | Baldwin Av. | M | 1977-06-07 |
| Kim Basinger | Baldwin Av. | F | 1979-05-07 |
| Debra Winger | A way | F | 1978-05-06 |
| Jane Fonda | Turner Av. | F | 1977-07-07 |
+--------------+-------------+--------+------------+

其中条件表达式同样支持常用编程语言中的基本运算。

运算符

基本运算符 语义 补充
= / <> / < / > / <= / >= 比较运算符 注意 = 而非 == ,部分 SQL 支持 !=
NOT / AND / OR 逻辑运算符 优先级 NOT > AND > OR

SQL 支持基本的运算符,如四则运算与括号等,此处略去。

特殊运算符 语义 示例 补充说明
IN 多值查找 WHERE movieType IN ("drama", "sciFic") 常用于子查询,将在其他章节介绍。
EXISTS 集合非空 WHERE EXISTS {子查询} 检测子查询返回是否为空,将在其他章节介绍。
BETWEEN AND 区间比较 WHERE length BETWEEN 120 AND 150 等价于 WHERE 120 <= length AND length <= 150
LIKE 模式匹配 WHERE title LIKE "star %" Mysql 的模式匹配仅支持 % 匹配 0\ge 0 个字符,_ 匹配 11 个字符
IS NULL 为空 WHERE length IS NULL 由于 NULL 在运算中的特殊性,必要时使用 IS NULL

使用运算符进行组合筛选的示例:

1
2
3
4
5
6
7
8
-- 语句过长使用换行可以更加直观
SELECT
*
FROM
Movies
WHERE
title LIKE "star %" AND
(year <= 2000 OR studioName = "Paramount");
1
2
3
4
5
6
7
+--------------------+------+--------+-----------+------------+-----------+
| title | year | length | movieType | studioName | producerC |
+--------------------+------+--------+-----------+------------+-----------+
| Star Trek | 1979 | NULL | sciFic | Paramount | 444 |
| Star Trek: Nemesis | 2002 | 116 | sciFic | Paramount | 321 |
| Star Wars | 1977 | 124 | sciFic | Fox | 555 |
+--------------------+------+--------+-----------+------------+-----------+

计算字段

计算字段与物理字段

计算字段 不存在于物理表中更不占用磁盘,它是在执行查询语句时,基于物理表中的已有字段得到的字段。从效率的角度,计算字段 在执行语句时计算,这样做既节约了内存又方便修改,但在查询时耗费了额外的之间。

计算字段 直接在 SELECT 语句中与物理字段直接替换使用即可,另外建议给计算字段设置别名。

1
SELECT {计算表达式} [AS {别名}] FROM {表名};
1
2
3
4
5
6
7
SELECT 
title,
CONCAT(studioName, " ", movieType, " ", year)
AS description
-- CONCAT 是字符串连接函数, 不同 SQL 版本各不相同
FROM
Movies;
1
2
3
4
5
6
SELECT 
title,
CONCAT(studioName, " ", movieType, " ", year)
-- 没有别名的版本
FROM
Movies;
1
2
3
4
5
6
SELECT 
*, -- 依然可以使用 *
CONCAT(studioName, " ", movieType, " ", year)
AS description
FROM
Movies;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+--------------------------+----------------------------+
| title | description |
+--------------------------+----------------------------+
| Empire Strikes Back | Fox drama 1980 |
| My people,My country | huaxia feature 2019 |
| Gone With the Wind | MGM drama 1938 |
| Logan's run | MGM drama 1977 |
| Pretty Woman | Disney drama 1990 |
| Star Trek | Paramount sciFic 1979 |
| Star Trek: Nemesis | Paramount sciFic 2002 |
| Star Wars | Fox sciFic 1977 |
| Terms of Endearment | MGM drama 1983 |
| The Man Who Wasn't There | USA Entertainm comedy 2001 |
| The Usual Suspects | MGM drama 1995 |
+--------------------------+----------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+--------------------------+-----------------------------------------------+
| title | CONCAT(studioName, " ", movieType, " ", year) |
+--------------------------+-----------------------------------------------+
| Empire Strikes Back | Fox drama 1980 |
| My people,My country | huaxia feature 2019 |
| Gone With the Wind | MGM drama 1938 |
| Logan's run | MGM drama 1977 |
| Pretty Woman | Disney drama 1990 |
| Star Trek | Paramount sciFic 1979 |
| Star Trek: Nemesis | Paramount sciFic 2002 |
| Star Wars | Fox sciFic 1977 |
| Terms of Endearment | MGM drama 1983 |
| The Man Who Wasn't There | USA Entertainm comedy 2001 |
| The Usual Suspects | MGM drama 1995 |
+--------------------------+-----------------------------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+--------------------------+------+--------+-----------+----------------+-----------+----------------------------+
| title | year | length | movieType | studioName | producerC | description |
+--------------------------+------+--------+-----------+----------------+-----------+----------------------------+
| Empire Strikes Back | 1980 | 111 | drama | Fox | 555 | Fox drama 1980 |
| My people,My country | 2019 | 158 | feature | huaxia | 100 | huaxia feature 2019 |
| Gone With the Wind | 1938 | 238 | drama | MGM | 123 | MGM drama 1938 |
| Logan's run | 1977 | 120 | drama | MGM | 888 | MGM drama 1977 |
| Pretty Woman | 1990 | 119 | drama | Disney | 999 | Disney drama 1990 |
| Star Trek | 1979 | NULL | sciFic | Paramount | 444 | Paramount sciFic 1979 |
| Star Trek: Nemesis | 2002 | 116 | sciFic | Paramount | 321 | Paramount sciFic 2002 |
| Star Wars | 1977 | 124 | sciFic | Fox | 555 | Fox sciFic 1977 |
| Terms of Endearment | 1983 | 132 | drama | MGM | 123 | MGM drama 1983 |
| The Man Who Wasn't There | 2001 | 116 | comedy | USA Entertainm | 777 | USA Entertainm comedy 2001 |
| The Usual Suspects | 1995 | 106 | drama | MGM | 999 | MGM drama 1995 |
+--------------------------+------+--------+-----------+----------------+-----------+----------------------------+

函数

此外,各类 SQL 均提供了相关的函数用于计算,这通常被用于计算字段或筛选条件中,例如上面使用到的 CONCAT 函数。但是各类 SQL 中的函数各不相同,因此从可移植性的角度,我们应该尽量减少函数的使用。

下面以 MySQL 为例,举例一些常用函数。

函数 作用 补充
CONVERT(expr, type) 数据类型转换 在其他 SQL 中有 CAST,也有使用多函数的。
函数 作用 补充
SUBSTR(field, start, length) 截取子串 start11 索引的,field 自动转为字符型。
CONCAT(field1, field2) 拼接字符串 field 自动转为字符型。
LENGTH(field) 获取字符串长度 field 自动转为字符型。
LOWER(field) / LOWER(field) 获取字符串大写 / 小写 field 自动转为字符型。
LTRIM(field) / RTRIM(field) / TRIM(field) 去除左 / 右 / 左右空字符 field 自动转为字符型。
SOUNDEX(field) 获取发音,用于查找发音 field 自动转为字符型。
函数 作用 补充
NOW() 获取当前日期时间 2023-10-11 14:32:17
CURDATE() 获取当前日期 2023-10-11
CURTIME() 获取当前时间 14:32:17
DATE(datetime) / TIME(datetime) 获取日期 / 时间 1970-01-01 / 08:00:00
YEAR(datetime) / MONTH(datetime) / DAY(datetime) 获取年 / 月 / 日 1970 / 1 / 1
HOUR(datetime) / MINUTE(datetime) / SECOND(datetime) 获取时 / 分 / 秒 8 / 0 / 0
MONTHNAME(datetime) / DAYNAME(datetime) 获取月份名 / 工作日名 January / Thursday
DATE_FORMAT(datetime, format) 格式化时间输出 %Y-%m-%d %H:%i:%s
UNIX_TIMESTAMP(datetime) 时间类型转时间戳
FROM_UNIXTIME(datetime) 时间戳转时间类型
函数 作用 补充
ABS(num) 绝对值
ROUND(num) / ROUND(num, digit) 四舍五入 / 四舍五入到若干小数
SIN(num) / COS(num) / TAN(num) 三角函数
EXP(num) / LOG(num) 自然指数与自然对数
POW(base, exponent) / LOG(base, real) / SQRT(base) 指数与对数与开方
EXP(1) / PI() 自然底数与圆周率

数据排序 ORDER BY

基本格式

SELECT 语句可以使用 ORDER BY 进行数据排序。格式为:

1
{SELECT 语句} [WHERE {条件表达式}] ORDER BY {排序关键字};

注意事项:

  • 排序关键字可以是计算字段,即一个表达式。
  • 如果未使用 ORDER BY,关键字应当被假定是无序的;但主键总是排序的。
1
SELECT * FROM MovieStar;  -- 未排序前的状态
1
SELECT * FROM MovieStar ORDER BY birthDate;
1
SELECT * FROM Movies ORDER BY length * producerC;  -- 可以是计算字段
1
2
3
4
5
6
7
8
9
10
+----------------+-------------+--------+------------+
| name | address | gender | birthDate |
+----------------+-------------+--------+------------+
| Alec Baldwin | Baldwin Av. | M | 1977-06-07 |
| Kim Basinger | Baldwin Av. | F | 1979-05-07 |
| Debra Winger | A way | F | 1978-05-06 |
| Harrison Ford | Prefect Rd. | M | 1955-05-05 |
| Jack Nicholson | X path | M | 1949-05-05 |
| Jane Fonda | Turner Av. | F | 1977-07-07 |
+----------------+-------------+--------+------------+
1
2
3
4
5
6
7
8
9
10
+----------------+-------------+--------+------------+
| name | address | gender | birthDate |
+----------------+-------------+--------+------------+
| Jack Nicholson | X path | M | 1949-05-05 |
| Harrison Ford | Prefect Rd. | M | 1955-05-05 |
| Alec Baldwin | Baldwin Av. | M | 1977-06-07 |
| Jane Fonda | Turner Av. | F | 1977-07-07 |
| Debra Winger | A way | F | 1978-05-06 |
| Kim Basinger | Baldwin Av. | F | 1979-05-07 |
+----------------+-------------+--------+------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+--------------------------+------+--------+-----------+----------------+-----------+
| title | year | length | movieType | studioName | producerC |
+--------------------------+------+--------+-----------+----------------+-----------+
| Star Trek | 1979 | NULL | sciFic | Paramount | 444 |
| My people,My country | 2019 | 158 | feature | huaxia | 100 |
| Terms of Endearment | 1983 | 132 | drama | MGM | 123 |
| Gone With the Wind | 1938 | 238 | drama | MGM | 123 |
| Star Trek: Nemesis | 2002 | 116 | sciFic | Paramount | 321 |
| Empire Strikes Back | 1980 | 111 | drama | Fox | 555 |
| Star Wars | 1977 | 124 | sciFic | Fox | 555 |
| The Man Who Wasn't There | 2001 | 116 | comedy | USA Entertainm | 777 |
| The Usual Suspects | 1995 | 106 | drama | MGM | 999 |
| Logan's run | 1977 | 120 | drama | MGM | 888 |
| Pretty Woman | 1990 | 119 | drama | Disney | 999 |
+--------------------------+------+--------+-----------+----------------+-----------+

升序与降序

ORDER BY 可以使用 ASC(默认)/ DESC 表示升序和降序,将其放在排序关键字后面。

1
SELECT * FROM MovieStar ORDER BY birthDate ASC;
1
SELECT * FROM MovieStar ORDER BY birthDate DESC;
1
2
3
4
5
6
7
8
9
10
+----------------+-------------+--------+------------+
| name | address | gender | birthDate |
+----------------+-------------+--------+------------+
| Jack Nicholson | X path | M | 1949-05-05 |
| Harrison Ford | Prefect Rd. | M | 1955-05-05 |
| Alec Baldwin | Baldwin Av. | M | 1977-06-07 |
| Jane Fonda | Turner Av. | F | 1977-07-07 |
| Debra Winger | A way | F | 1978-05-06 |
| Kim Basinger | Baldwin Av. | F | 1979-05-07 |
+----------------+-------------+--------+------------+
1
2
3
4
5
6
7
8
9
10
+----------------+-------------+--------+------------+
| name | address | gender | birthDate |
+----------------+-------------+--------+------------+
| Kim Basinger | Baldwin Av. | F | 1979-05-07 |
| Debra Winger | A way | F | 1978-05-06 |
| Jane Fonda | Turner Av. | F | 1977-07-07 |
| Alec Baldwin | Baldwin Av. | M | 1977-06-07 |
| Harrison Ford | Prefect Rd. | M | 1955-05-05 |
| Jack Nicholson | X path | M | 1949-05-05 |
+----------------+-------------+--------+------------+

多关键字排序

ORDER BY 可以添加多个排序关键字,直接使用 , 分割即可:

1
{SELECT 语句} [WHERE {条件表达式}] ORDER BY {排序关键字} [ASC / DESC] [, {排序关键字} [ASC / DESC] ...];
1
SELECT * FROM MovieExec ORDER BY netWorth ASC, address DESC;
1
2
3
4
5
6
7
8
9
10
11
+-------------------+-------------+------+-----------+
| name | address | cert | netWorth |
+-------------------+-------------+------+-----------+
| Huangjianxin | NULL | 100 | NULL |
| Calvin Coolidge | Fast Lane | 123 | 20000000 |
| Stephen Spielberg | 123 ET road | 222 | 100000000 |
| Merv Griffin | Riot Rd. | 199 | 112000000 |
| Ted Turner | Turner Av. | 333 | 125000000 |
| Jane Fonda | Turner Av. | 567 | 200000000 |
| George Lucas | Oak Rd. | 555 | 200000000 |
+-------------------+-------------+------+-----------+

分页查询 LIMIT OFFSET

当数据表很大时,直接显示整张数据表不太现实,例如直接查询千万记录级别的数据表,可能直接导致内存爆炸。这时我们可以使用分页查询,仅显示数据表中一定数量的行。

1
{SELECT 语句} LIMIT {显示行数} [OFFSET {首行行号}]

注意行号是 0 索引的,LIMIT OFFSET 的两个参数都是非负数,OFFSET 可缺省为 0

1
2
3
SELECT COUNT(*) FROM test;
SELECT * FROM test LIMIT 10 OFFSET 0;
SELECT * FROM test LIMIT 10 OFFSET 10; -- 一般 OFFSET 是 LIMIT 的倍数
1
2
3
4
5
+----------+
| COUNT(*) |
+----------+
| 511232 |
+----------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
+----+----------+------+
| id | name | age |
+----+----------+------+
| 0 | wangwu | 11 |
| 1 | wangwu | 33 |
| 2 | wangwu | 10 |
| 3 | lisi | 21 |
| 4 | zhangsan | 43 |
| 5 | zhangsan | 48 |
| 6 | zhangsan | 30 |
| 7 | lisi | 50 |
| 8 | lisi | 20 |
| 9 | zhangsan | 29 |
+----+----------+------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
+----+----------+------+
| id | name | age |
+----+----------+------+
| 10 | zhangsan | 10 |
| 11 | lisi | 24 |
| 12 | zhangsan | 27 |
| 13 | lisi | 36 |
| 14 | zhangsan | 14 |
| 15 | wangwu | 47 |
| 16 | wangwu | 16 |
| 17 | zhangsan | 40 |
| 18 | wangwu | 19 |
| 19 | zhangsan | 23 |
+----+----------+------+

聚集函数与分组

聚集函数

聚集函数用于汇总数据,SQL 提供了 55 种聚集函数。另外,在不同 SQL 版本中,函数名可能各有不同。

聚集函数 功能 补充
COUNT(field) 字段非空值数量 参数可为 *,计数表格行数,即使整行均为 NULL 也计数,使用 DISTINCT 也计数全部行数。仅 COUNT 参数可 *
MIN(field) 字段最小值 NULL 值忽略,全 NULL 返回 NULL
MAX(field) 字段最大值 NULL 值忽略,全 NULL 返回 NULL
SUM(field) 字段求和 NULL 值忽略,全 NULL 返回 NULL
AVG(field) 字段平均值 =SUM()COUNT()=\frac{\text{SUM}()}{\text{COUNT}()}COUNT()=0\text{COUNT}()=0 返回 NULL
VAR_POP(field) 字段标准差 =AVG(POW(XAVG(), 2))= \text{AVG}(\text{POW}(X - \text{AVG}(),~2))COUNT()=0\text{COUNT}()=0 返回 NULL
STDDEV(field) 字段标准差 =SQRT(VAR_POP())= \text{SQRT}(\text{VAR\_POP}())COUNT()=0\text{COUNT}()=0 返回 NULL
GROUP_CONCAT(field [SEPARATOR separator]) 字段值连接 将该分组该字段的值按分隔符连接,分隔符可缺省为 ,

注释: 聚集函数的对象为分组,分组使用下一章节中的 GROUP BY 创建,是一些具有相同属性的行的集合。未创建分组的,全部行为一个分组,因此在目前的示例中我们都只能看到一行输出。

1
SELECT MIN(year), MAX(year), COUNT(length), SUM(producerC), AVG(producerC) FROM Movies;
1
2
3
4
5
6
7
8
SELECT 
MIN(year) AS minYear,
MAX(year) AS maxYear,
COUNT(length) AS cntLength,
SUM(producerC) AS sumProducerC,
AVG(producerC) AS avgProducerC
FROM
Movies;
1
2
3
4
5
+-----------+-----------+---------------+----------------+----------------+
| MIN(year) | MAX(year) | COUNT(length) | SUM(producerC) | AVG(producerC) |
+-----------+-----------+---------------+----------------+----------------+
| 1938 | 2019 | 10 | 5884 | 534.9091 |
+-----------+-----------+---------------+----------------+----------------+
1
2
3
4
5
+---------+---------+-----------+--------------+--------------+
| minYear | maxYear | cntLength | sumProducerC | avgProducerC |
+---------+---------+-----------+--------------+--------------+
| 1938 | 2019 | 10 | 5884 | 534.9091 |
+---------+---------+-----------+--------------+--------------+

分组聚集 GROUP BY

基本格式

GROUP BY 用于设置分组,分组是一些具有相同属性的行的集合,分组是聚集函数的计算范围。在输出的表格中每个分组为一行,使用 GROUP BY 才能发挥出聚集函数的作用。

1
{SELECT 语句} GROUP BY {分组关键字};

GROUP BY 同样支持多关键字。

1
{SELECT 语句} GROUP BY {分组关键字} [, 分组关键字];
1
2
SELECT studioName, COUNT(length) FROM Movies GROUP BY studioName; 
-- 使用聚合函数计数某工作室出品的电影中有记录电影时长的数量
1
2
SELECT studioName, movieType, COUNT(*) FROM Movies GROUP BY studioName, movieType;
-- 使用聚合函数计数某工作室出品的某类型电影的数量
1
2
3
4
5
6
7
8
9
10
+----------------+---------------+
| studioName | COUNT(length) |
+----------------+---------------+
| Fox | 2 |
| huaxia | 1 |
| MGM | 4 |
| Disney | 1 |
| Paramount | 1 |
| USA Entertainm | 1 |
+----------------+---------------+
1
2
3
4
5
6
7
8
9
10
11
+----------------+-----------+----------+
| studioName | movieType | COUNT(*) |
+----------------+-----------+----------+
| Fox | drama | 1 |
| huaxia | feature | 1 |
| MGM | drama | 4 |
| Disney | drama | 1 |
| Paramount | sciFic | 2 |
| Fox | sciFic | 1 |
| USA Entertainm | comedy | 1 |
+----------------+-----------+----------+

注意事项

  • GROUP BY 不会进行排序的工作,它的分组依然是乱序的。
  • SELECT 语句中的字段必须是分组关键字、引用 以物理字段作 分组关键字的计算字段、聚集函数。需要注意的是,如果分组关键字是计算字段,SELECT 语句中的计算字段不能引用它,但聚集函数的参数可以任意引用。

以下是一些关于第二条的示例,有正有误:

1
SELECT * FROM Movies GROUP BY studioName;
显示答案

错误,部分物理字段不属于分组关键字。

分析 SQL 这样做的原因,由于每个分组使用单行显示,并且分组内仅保证相同属性 studioName,因此无法确定的输出其他字段(如 title 字段)。

1
SELECT CONCAT(studioName, " ", movieType), COUNT(*) FROM Movies GROUP BY studioName, movieType;
显示答案

正确,计算字段是对分组关键字的引用。

分析 SQL 这样做的原因,每个分组内保证相同属性 studioNamemovieType,因此可以确定输出 UPPER(studioName) 字段。

1
2
3
4
5
6
7
8
9
10
11
+------------------------------------+----------+
| CONCAT(studioName, " ", movieType) | COUNT(*) |
+------------------------------------+----------+
| Fox drama | 1 |
| huaxia feature | 1 |
| MGM drama | 4 |
| Disney drama | 1 |
| Paramount sciFic | 2 |
| Fox sciFic | 1 |
| USA Entertainm comedy | 1 |
+------------------------------------+----------+
1
2
3
4
5
6
7
SELECT 
CONCAT(studioName, " ", movieType),
COUNT(*)
FROM
Movies
GROUP BY
CONCAT(studioName, " ", movieType);
显示答案

正确,计算字段是分组关键字。

虽然是计算字段,但是对于 SQL 而言由于两个字段完全相同,直接引用即可。

1
2
3
4
5
6
7
8
9
10
11
+------------------------------------+----------+
| CONCAT(studioName, " ", movieType) | COUNT(*) |
+------------------------------------+----------+
| Fox drama | 1 |
| huaxia feature | 1 |
| MGM drama | 4 |
| Disney drama | 1 |
| Paramount sciFic | 2 |
| Fox sciFic | 1 |
| USA Entertainm comedy | 1 |
+------------------------------------+----------+
1
2
3
4
5
6
7
SELECT 
UPPER(CONCAT(studioName, " ", movieType)),
COUNT(*)
FROM
Movies
GROUP BY
CONCAT(studioName, " ", movieType);
显示答案

错误,计算字段不能引用 GROUP BY 中的计算字段,只能直接相等(如示例3)。

从 SQL 实现的角度考虑,显然在进行 UPPER 操作后我们可以唯一的确定输出的值,但是当两个计算字段之间的逻辑变得复杂时,程序很难再推导出两个计算字段之间的关系,于是 SQL 索性禁止了所有此类行为。

1
2
3
4
5
6
7
SELECT 
movieType,
AVG(length * producerC)
FROM
Movies
GROUP BY
movieType;
显示答案

正确,聚合函数可以任意的引用和计算。因为聚合函数的本质就是将数据汇总输出一个值。

1
2
3
4
5
6
7
8
+-----------+-------------------------+
| movieType | AVG(length * producerC) |
+-----------+-------------------------+
| drama | 73075.0000 |
| feature | 15800.0000 |
| sciFic | 53028.0000 |
| comedy | 90132.0000 |
+-----------+-------------------------+

分组过滤 HAVING

WHERE 不同的是,HAVING 过滤的对象是分组,而 WHERE 的过滤对象为行。HAVING 通常与 GROUP BY 一同使用,必须放在 GROUP BY 之后。如果你无法很好的区分 WHEREHAVING 只需要记住,在 GROUP BY 之前进行的筛选是 WHERE,在 GROUP BY 之后进行的筛选是 HAVING

1
{SELECT 语句} GROUP BY {分组关键字} HAVING {条件表达式}

由于 HAVING 过滤的对象是分组。在 HAVING 条件表达式中,可以使用聚集函数;而在 WHERE 条件表达式中,不可使用聚集函数。但 HAVING 条件表达式中的引用具有与前面提到的 GROUP BY 相同的约束,详见 分组聚集 GROUP BY - 注意事项

1
2
3
4
5
6
7
8
9
10
SELECT 
studioName,
COUNT(*)
FROM
Movies
GROUP BY
studioName
HAVING
COUNT(*) > 1 AND
LENGTH(studioName) > 3;
1
2
3
4
5
+------------+----------+
| studioName | COUNT(*) |
+------------+----------+
| Paramount | 2 |
+------------+----------+

SELECT 子句顺序

至此我们介绍了 44 种子句,SQL 严格定义了这些关键字的顺序。SELECT 查询命令也是按照这个顺序从左往右执行的。

关键字 作用 顺序级
WHERE 行级过滤 1
GROUP BY 分组 2
HAVING 组级过滤 3
ORDER BY 排序 4
LIMIT OFFSET 分页查询 5

下面算是一个综合应用吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT 
studioName,
COUNT(*)
FROM
Movies
WHERE
year >= 1950 -- 首先去除 1950 年前的作品
GROUP BY
studioName -- 然后将剩余作品按工作室分组
HAVING
COUNT(*) > 1 -- 再去掉分组后分组包含作品 <= 1 的工作室
ORDER BY
COUNT(*) DESC, -- 最后将数据集按作品数降序, 工作室名称升序排列
studioName;
1
2
3
4
5
6
7
+------------+----------+
| studioName | COUNT(*) |
+------------+----------+
| MGM | 3 |
| Fox | 2 |
| Paramount | 2 |
+------------+----------+