MySQL关于查询语句使用的一些关键字

1. MySQL基础

1.1. 查询语句

1.1.1. SELECT

SELECT 语法

SELECT columns_list
FROM table_name;
    • SELECT 就是进行查询操作,后可以跟着一个或多个数据表的字段。

SELECT 语句的正确语义应是 FROM table_name SELECT columns_list,即:从某个表检索某几列数据。MySQL 解析 SELECT 语句的时候,会首先评估 FROM 子句,再评估 SELECT 子句。

在 MySQL 中,要查询的数据不存在于任何表中,这时可以省略 FROM 子句。语法如下:

SELECT expression_list

例如:

SELECT NOW();

// 输出结果
+---------------------+
| NOW()               |
+---------------------+
| 2021-09-07 22:45:33 |
+---------------------+
1 row in set (0.00 sec)
SELECT 1+2;

//输出结果
+-----+
| 1+2 |
+-----+
|   3 |
+-----+
1 row in set (0.00 sec)

没有 FROM 子句的情况,也可以添加一个虚拟表 dual。

SELECT NOW() FROM dual;
SELECT 1+2 FROM dual;

运算结果和上面的实例完全相同。

dual 表是一个虚拟表,完全可以忽略。它存在的目的只是让 SQL 看起来更加工整。

1.1.2. WHERE

where子句在进行select查询时可以用来指定搜索条件,UPDATE 和 DELETE 语句中,用来指定要更新或删除的行。也可以是使用 AND , ORNOT 逻辑运算符一个或多个表达式的组合。

MySQL 提供了很多比较运算符,下表列出了可用于 WHERE 子句中的比较运算符。

比较运算符

说明

举例

=

等于

age = 18

<>

不等于

age <> 18

!=

不等于

age != 18

>

大于,通常用于比较数字或者日期

age > 18

>=

大于等于,通常用于比较数字或者日期

age >= 18

<

小于,通常用于比较数字或者日期

age < 18

<=

小于等于,通常用于比较数字或者日期

age <= 18

IN

判断值是否在一个集合中

age IN (18, 19)

NOT IN

判断值是否不在一个集合中

age NOT IN (18, 19)

BETWEEN

判断值是否介于两个数中间

age BETWEEN 16 AND 18

LIKE

模糊匹配

name LIKE 'A%'

IS NULL

是否为 NULL

name IS NULL

IS NOT NULL

是否不为 NULL

name IS NOT NULL

注意: 在 SQL 中,比较两个值是否相等的运算符是 =,而不是 ==

1.1.3. AND

AND 左右两个条件都成立,结果才返回真,否则返回假或者 NULL。MySQL 中没有布尔类型,AND 的运算结果是 1(true), 0(false), 或者 NULL。

AND 运算符的运算规则如下:

    • 两个操作数都为true(非0),则 AND 运算的结果为 1
SELECT 1 AND 1, 1 AND 2;
//运算结果
+---------+---------+
| 1 AND 1 | 1 AND 2 |
+---------+---------+
|       1 |       1 |
+---------+---------+
    • 有一个操作数为 0 (FALSE),则 AND 运算的结果为 0
SELECT
    0 AND 0,
    0 AND 1,
    0 AND 2,
    0 AND NULL;
//结果
+---------+---------+---------+------------+
| 0 AND 0 | 0 AND 1 | 0 AND 2 | 0 AND NULL |
+---------+---------+---------+------------+
|       0 |       0 |       0 |          0 |
+---------+---------+---------+------------+
    • 有一个为 NULL,就返回 NULL
SELECT 1 AND NULL, 2 AND NULL, NULL AND NULL;
//结果
+------------+------------+---------------+
| 1 AND NULL | 2 AND NULL | NULL AND NULL |
+------------+------------+---------------+
|       NULL |       NULL |          NULL |
+------------+------------+---------------+

操作数的前后顺序不影响 AND 操作符的运算结果。

1.1.4. OR

OR ,两个操作数中的一个为1(true)时,结果就返回1(true),否则返回0(false)或者 NULL

OR 运算符的运算规则如下:

    • 两个操作数中有一个操作数为 1 (true),则 OR 运算的结果为 1
SELECT 1 OR 1, 1 OR 0, 1 OR NULL, 2 OR 0;
//结果
+--------+--------+-----------+--------+
| 1 OR 1 | 1 OR 0 | 1 OR NULL | 2 OR 0 |
+--------+--------+-----------+--------+
|      1 |      1 |         1 |      1 |
+--------+--------+-----------+--------+
    • or连接的所有操作数都为 0 (false),则 OR 运算的结果为 0
SELECT 0 OR 0;
//结果
+--------+
| 0 OR 0 |
+--------+
|      0 |
+--------+
    • or连接的操作数在没有1(true)的情况下,有null就返回null
SELECT NULL OR 0, NULL or NULL;
//结果
+-----------+--------------+
| NULL OR 0 | NULL or NULL |
+-----------+--------------+
|      NULL |         NULL |
+-----------+--------------+

操作数的前后顺序不影响 OR 操作符的运算结果

有1就是1,全0才是0,没1都是null

1

0

NULL

1

1

1

1

0

1

0

NULL

NULL

1

NULL

NULL

1.1.5. IN

SQL 查询的时候,用IN来判断左侧的值是否存在与右侧,右侧可以是1个值也可以是多个值。如果包含返回 1,否则返回 0

    • IN 运算符是多个 OR 运算符组合的简化版本。比如下面的 IN 语句:
name IN ('Alice', 'Tim', 'Jack')
//相当于下面的 OR 语句:
name = 'Alice' OR name = 'Tim' OR name = 'Jack'
    • 当左侧和右侧都不是 NULL 时,右侧值列表中包含左侧的值时返回 1,否则返回 0
SELECT 1 IN (1, 2), 3 IN (1, 2), 'A' IN ('A', 'B'), 'C' IN ('A', 'B');
//结果
+-------------+-------------+-------------------+-------------------+
| 1 IN (1, 2) | 3 IN (1, 2) | 'A' IN ('A', 'B') | 'C' IN ('A', 'B') |
+-------------+-------------+-------------------+-------------------+
|           1 |           0 |                 1 |                 0 |
+-------------+-------------+-------------------+-------------------+
    • 左侧操作数为 NULL,返回 NULL
SELECT NULL IN (1, 2), NULL IN (1, 2, NULL);
//结果
+----------------+----------------------+
| NULL IN (1, 2) | NULL IN (1, 2, NULL) |
+----------------+----------------------+
|           NULL |                 NULL |
+----------------+----------------------+
    • 当右侧值列表含有 NULL,但是包含了左侧的值,返回 1,否则返回 NULL
SELECT 1 IN (1, NULL), 2 IN (1, NULL);
//结果
+----------------+----------------+
| 1 IN (1, NULL) | 2 IN (1, NULL) |
+----------------+----------------+
|              1 |           NULL |
+----------------+----------------+

MySQL IN 实例

WHERE 子句中也可以使用 IN 运算符。IN 除了与值列表比较,还能与子查询进行比较。

    • 使用 WHERE 子句查找姓氏为 ALLENDAVIS 的所有演员
SELECT * FROM actor WHERE last_name IN ('ALLEN', 'DAVIS');
//结果
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|      118 | CUBA       | ALLEN     | 2006-02-15 04:34:33 |
|      145 | KIM        | ALLEN     | 2006-02-15 04:34:33 |
|      194 | MERYL      | ALLEN     | 2006-02-15 04:34:33 |
|        4 | JENNIFER   | DAVIS     | 2006-02-15 04:34:33 |
|      101 | SUSAN      | DAVIS     | 2006-02-15 04:34:33 |
|      110 | SUSAN      | DAVIS     | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+

1.1.6. NOT IN

NOT ,用来否定一个操作。NOT ININ 的否定操作。

NOT IN 运算符的运算规则:

    • 右侧值列表不包含左侧的值时条件成立,返回 1,否则返回 0
SELECT 1 NOT IN (1, 2), 3 NOT IN (1, 2), 'A' NOT IN ('A', 'B'), 'C' NOT IN ('A', 'B');
//结果
+-----------------+-----------------+-----------------------+-----------------------+
| 1 NOT IN (1, 2) | 3 NOT IN (1, 2) | 'A' NOT IN ('A', 'B') | 'C' NOT IN ('A', 'B') |
+-----------------+-----------------+-----------------------+-----------------------+
|               0 |               1 |                     0 |                     1 |
+-----------------+-----------------+-----------------------+-----------------------+
    • 左侧操作数是 NULL,返回 NULL
SELECT NULL NOT IN (1, 2), NULL NOT IN (1, 2, NULL);
//结果
+--------------------+--------------------------+
| NULL NOT IN (1, 2) | NULL NOT IN (1, 2, NULL) |
+--------------------+--------------------------+
|               NULL |                     NULL |
+--------------------+--------------------------+
    • 右侧有null且条件不成立,返回null
SELECT 1 NOT IN (1, NULL), 2 NOT IN (1, NULL);
//结果
+--------------------+--------------------+
| 1 NOT IN (1, NULL) | 2 NOT IN (1, NULL) |
+--------------------+--------------------+
|                  0 |               NULL |
+--------------------+--------------------+

1.1.7. BETWEEN

BETWEEN确定一个值是不是存在两个值的范围内。常用于判断一个值是不是在数字和日期之间。

MySQL BETWEEN 语法:

expression BETWEEN min AND max
expression NOT BETWEEN min AND max

使用说明: 左侧是字段名,表达式都可以,右侧是范围。

MySQL BETWEEN 运算规则:

当字段的值或者给定的值在 minmax 两个值之间时,返回 1。否则,返回 0

    • 左侧的值在 minmax 之间时, BETWEEN 返回 1,否则返回 0
SELECT
    1 BETWEEN 1 AND 3,
    2 BETWEEN 1 AND 3,
    3 BETWEEN 1 AND 3,
    4 BETWEEN 1 AND 3;
//结果
+-------------------+-------------------+-------------------+-------------------+
| 1 BETWEEN 1 AND 3 | 2 BETWEEN 1 AND 3 | 3 BETWEEN 1 AND 3 | 4 BETWEEN 1 AND 3 |
+-------------------+-------------------+-------------------+-------------------+
|                 1 |                 1 |                 1 |                 0 |
+-------------------+-------------------+-------------------+-------------------+
    • 有一个 NULL 时, BETWEEN 运算符就返回 NULL
SELECT
    NULL BETWEEN 1 AND 3,
    1 BETWEEN NULL AND 3,
    1 BETWEEN 1 AND NULL;
//结果
+----------------------+----------------------+----------------------+
| NULL BETWEEN 1 AND 3 | 1 BETWEEN NULL AND 3 | 1 BETWEEN 1 AND NULL |
+----------------------+----------------------+----------------------+
|                 NULL |                 NULL |                 NULL |
+----------------------+----------------------+----------------------+

1.1.8. LIKE

LIKE 运算符根据指定的模式过滤数据,一般用于模糊匹配字符数据。

expression LIKE pattern

说明:左侧是字段名,表达式都可以,右侧是一个字符串模式。支持两个通配符: %_

      • % 匹配0个或多个任意字符。
      • _ 匹配单个任意字符。
      • 如果匹配通配符,使用 \ 转义字符,如 \% 就表示%和 \_就表示_。
      • 通配符匹配文本时,不区分字母大小写。
      • 左侧和右侧匹配,LIKE 运算符返回 1,否则返回 0

比如:

      • a% 匹配以字符 a 开头的任意长度的字符串。
      • %a 匹配以字符 a 结尾的任意长度的字符串。
      • %a% 匹配包含字符 a 的任意长度的字符串。
      • %a%b% 匹配同时包含字符 abab 前面的任意长度的字符串。
      • a_ 匹配以字符 a 开头长度为 2 字符串。
      • _a 匹配以字符 a 结尾长度为 2 字符串。

MySQL LIKE 运算规则:

    • LIKE左侧值匹配右侧是,返回 1。否则,返回 0
SELECT 'a' LIKE 'a', 'a' LIKE 'a%', 'ab' LIKE 'a%', 'ab' LIKE '%a';
//结果
+--------------+---------------+----------------+----------------+
| 'a' LIKE 'a' | 'a' LIKE 'a%' | 'ab' LIKE 'a%' | 'ab' LIKE '%a' |
+--------------+---------------+----------------+----------------+
|            1 |             1 |              1 |              0 |
+--------------+---------------+----------------+----------------+


SELECT 'a' LIKE 'a_', 'ab' LIKE 'a_', 'abc' LIKE 'a_';
//结果
+---------------+----------------+-----------------+
| 'a' LIKE 'a_' | 'ab' LIKE 'a_' | 'abc' LIKE 'a_' |
+---------------+----------------+-----------------+
|             0 |              1 |               0 |
+---------------+----------------+-----------------+
    • LIKE 两侧有一个为null,返回 NULL。
SELECT NULL LIKE 'a%', 'a' LIKE NULL;
//结果
+----------------+---------------+
| NULL LIKE 'a%' | 'a' LIKE NULL |
+----------------+---------------+
|           NULL |          NULL |
+----------------+---------------+

MySQL LIKE 实例:

WHERE 子句中可以使用 LIKE 运算符。

使用 % 匹配开头

SELECT * FROM actor WHERE first_name LIKE 'P%';
//结果
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|        1 | PENELOPE   | GUINESS   | 2006-02-15 04:34:33 |
|       46 | PARKER     | GOLDBERG  | 2006-02-15 04:34:33 |
|       54 | PENELOPE   | PINKETT   | 2006-02-15 04:34:33 |
|      104 | PENELOPE   | CRONYN    | 2006-02-15 04:34:33 |
|      120 | PENELOPE   | MONROE    | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+

使用 % 匹配结尾

SELECT * FROM actor WHERE first_name LIKE '%ES';
//结果
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|       48 | FRANCES    | DAY-LEWIS | 2006-02-15 04:34:33 |
|       84 | JAMES      | PITT      | 2006-02-15 04:34:33 |
|      126 | FRANCES    | TOMEI     | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+

使用 % 匹配包含字符

SELECT * FROM actor WHERE first_name LIKE '%AM%';
//结果
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|       24 | CAMERON    | STREEP    | 2006-02-15 04:34:33 |
|       63 | CAMERON    | WRAY      | 2006-02-15 04:34:33 |
|       71 | ADAM       | GRANT     | 2006-02-15 04:34:33 |
|       84 | JAMES      | PITT      | 2006-02-15 04:34:33 |
|      111 | CAMERON    | ZELLWEGER | 2006-02-15 04:34:33 |
|      132 | ADAM       | HOPPER    | 2006-02-15 04:34:33 |
|      175 | WILLIAM    | HACKMAN   | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+

使用 _匹配单个字符

SELECT * FROM actor WHERE first_name LIKE '_AY';
//结果
+----------+------------+-----------+---------------------+
| actor_id | first_name | last_name | last_update         |
+----------+------------+-----------+---------------------+
|       55 | FAY        | KILMER    | 2006-02-15 04:34:33 |
|       64 | RAY        | JOHANSSON | 2006-02-15 04:34:33 |
|      147 | FAY        | WINSLET   | 2006-02-15 04:34:33 |
|      156 | FAY        | WOOD      | 2006-02-15 04:34:33 |
+----------+------------+-----------+---------------------+

NOT LIKE

SELECT * FROM category WHERE name NOT LIKE 'A%';
//结果
+-------------+-------------+---------------------+
| category_id | name        | last_update         |
+-------------+-------------+---------------------+
|           3 | Children    | 2006-02-15 04:46:27 |
|           4 | Classics    | 2006-02-15 04:46:27 |
|           5 | Comedy      | 2006-02-15 04:46:27 |
|           6 | Documentary | 2006-02-15 04:46:27 |
|           7 | Drama       | 2006-02-15 04:46:27 |
|           8 | Family      | 2006-02-15 04:46:27 |
|           9 | Foreign     | 2006-02-15 04:46:27 |
|          10 | Games       | 2006-02-15 04:46:27 |
|          11 | Horror      | 2006-02-15 04:46:27 |
|          12 | Music       | 2006-02-15 04:46:27 |
|          13 | New         | 2006-02-15 04:46:27 |
|          14 | Sci-Fi      | 2006-02-15 04:46:27 |
|          15 | Sports      | 2006-02-15 04:46:27 |
|          16 | Travel      | 2006-02-15 04:46:27 |
+-------------+-------------+---------------------+

1.1.9. REGEXP(正则表达式)

刚刚知道SQL也有正则表达式。在搜索字符串方面更强大,可搜索更复杂的模板。

REGEXP实例:

select * from customers where last_name like '%field%'
//等效于:
select * from customers where last_name regexp 'field'

正则表达式可以组合来表达更复杂的字符串模式

//查询以mac开头 或者 以field结尾 或者 包含rose的数据
where last_name regexp '^mac|field$|rose'
//查找含ge/ie或ef/em/eq的
where last_name regexp '[gi]e|e[fmq]' 
// 查询e前面包含a-h的数据 或者 e后面包含c-j的数据
where last_name regexp '[a-h]e|e[c-j]'

REGEXP常用通配符:

    • . :匹配任意单个字符,除了换行符 \n 之外的任何字符。
    • * :匹配前面的字符零次或多次。
    • + :匹配前面的字符一次或多次。
    • ? :匹配前面的字符零次或一次。
    • ^ :匹配输入字符串的开头。
    • $ :匹配输入字符串的结尾。
    • [...] :字符类,匹配方括号中任意字符。例如,[abc] 匹配 "a"、"b" 或 "c" 中的任何一个字符。
    • [^...] :否定字符类,匹配除了方括号中的字符之外的任何字符。例如,[^abc] 匹配除了 "a"、"b"、"c" 之外的任何字符。
    • | :逻辑或运算符,匹配两个模式中的任意一个。
    • \ :转义字符,用于转义具有特殊含义的字符,使其成为普通字符。例如,\. 匹配实际的点而不是任意字符。

1.1.10. IS NULL

IS NULL 用来判断一个值是不是 NULL,如果是 NULL 返回 1,否则返回 0

expression IS NULL
expression IS NOT NULL

说明:左侧是字段名,表达式都可以。

MySQL IS NULL 运算规则:

    • IS NULL 左侧值是 NULL 时,返回 1,否则返回 0
SELECT
    NULL IS NULL,
    0 IS NULL,
    1 IS NULL,
    (NULL IN (NULL)) IS NULL,
    (1+1) IS NULL;
//结果
+--------------+-----------+-----------+--------------------------+---------------+
| NULL IS NULL | 0 IS NULL | 1 IS NULL | (NULL IN (NULL)) IS NULL | (1+1) IS NULL |
+--------------+-----------+-----------+--------------------------+---------------+
|            1 |         0 |         0 |                        1 |             0 |
+--------------+-----------+-----------+--------------------------+---------------+
    • IS NOT NULL 左侧值不是 NULL 时,返回 1,否则返回 0
SELECT
    NULL IS NOT NULL,
    0 IS NOT NULL,
    1 IS NOT NULL;
//结果
+------------------+---------------+---------------+
| NULL IS NOT NULL | 0 IS NOT NULL | 1 IS NOT NULL |
+------------------+---------------+---------------+
|                0 |             1 |             1 |
+------------------+---------------+---------------+

MySQL IS NULL 实例:

    • 以下 SQL 语句使用 IS NULL 查询 staff 表中没有设置密码的职员。
SELECT
    first_name, last_name, password
FROM
    staff
WHERE
    password IS NULL;
//结果
+------------+-----------+----------+
| first_name | last_name | password |
+------------+-----------+----------+
| Jon        | Stephens  | NULL     |
+------------+-----------+----------+

要查询密码不是null的职员,使用password IS NOT NULL

1.1.11. EXISTS

EXISTS 判断当前数据是否存在,会用在where子句中,在这个子句中执行一条查询语句,如果查询到了说明这个数据是存在的就会返回1(true),反之返回一个0(false)。

EXISTS 实例:

下面的实例查询 language 表的一些语种,该语种在 film 表中存在相关语种的影片。

下面这条查询语句会查询这张表的所有数据,说一下执行的流程,先执行最内层的查询语句,涉及到了两个表,拿film表的language_id去找language表的language_id如果两个值相等,EXISTS会返回true,外层的where判断是true,最外层查询就会输出这条语句,然后进行下一条语句的判断。

SELECT *
FROM language
WHERE EXISTS(
    SELECT *
    FROM film
    WHERE film.language_id = language.language_id
  );
//结果
+-------------+---------+---------------------+
| language_id | name    | last_update         |
+-------------+---------+---------------------+
|           1 | English | 2006-02-15 05:02:19 |
+-------------+---------+---------------------+
1 row in set (0.01 sec)

由EXISTS引出的子查询,目标列表达式通常都用 *,因为EXISTS的子查询只返回真值假值,给出列名无实际意义。

EXISTS 和 IN:

    • 有时候 EXISTS 可以使用 IN 来实现。
//EXISTS
SELECT *
FROM language
WHERE EXISTS(
    SELECT *
    FROM film
    WHERE film.language_id = language.language_id
  );
//IN
SELECT *
FROM language
WHERE language_id IN (
    SELECT DISTINCT language_id
    FROM film
  );

大多数情况下,使用 EXISTS 的语句的性能比对应的使用 IN 的语句要好。

在子查询中使用 TABLE 语句:

在 MySQL 8.0.19 和以后的版本中,可以直接在 EXISTS 或 NOT EXISTS 的子查询中使用 TABLE 语句。就像下面的一样:

//只有当表 t2 不为空时,才会选择表 t1 中的数据。
SELECT column1 FROM t1 WHERE EXISTS (TABLE t2);
//例如
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

1.1.12. ORDER BY

SELECT 语句返回的结果集默认是升序排序的。如果想改变结果的输出顺序,可以使用 ORDER BY 子句指定排序的字段以及升序排序还是降序排序。

MySQL ORDER BY 语法:

ORDER BY 子句中,可以指定一个或多个排序的字段。 ORDER BY 子句的语法如下:

SELECT
   column1, column2, ...
FROM
   table_name
[WHERE clause]
ORDER BY
   column1 [ASC|DESC],
   column2 [ASC|DESC],
   ...;

说明:

    • [ASC|DESC] 代表排序是升序还是降序,这是可选的,只能选一个,不能由升序又降序。
    • ASC 代表升序,DESC 代表降序。

MySQL ORDER BY 排序规则说明:

    • ORDER BY column1, column2;

ORDER BY 子句主排序按 column1 字段升序排序,在主排序的基础上,column1 字段如果有多个相同的行,再按 column2 字段升序排序。默认是升序排序,也可指定为降序排序DESC

MySQL ORDER BY 实例:

按多字段排序:

以下 SQL 语句使用 ORDER BY 子句先按演员姓氏升序排序,再按演员名字升序排序。

SELECT
    actor_id, first_name, last_name
FROM
    actor
ORDER BY last_name, first_name;
//结果
+----------+-------------+--------------+
| actor_id | first_name  | last_name    |
+----------+-------------+--------------+
|       58 | CHRISTIAN   | AKROYD       |
|      182 | DEBBIE      | AKROYD       |
|       92 | KIRSTEN     | AKROYD       |
|      118 | CUBA        | ALLEN        |
|      145 | KIM         | ALLEN        |
|      194 | MERYL       | ALLEN        |
....

按自定义顺序排序:

有时候按照字段的值排序不能满足要求,可以自定义排序。比如,需要按照电影分级 'G', 'PG', 'PG-13', 'R', 'NC-17' 的顺序对影片进行排序。

可以理解为按照列表中元素的索引位置进行排序。分别使用 CASE 子句或 FIELD() 函数实现它。

根据影片的等级按照的 'G', 'PG', 'PG-13', 'R', 'NC-17' 顺序对影片进行排序。

SELECT
    film_id, title, rating
FROM
    film
ORDER BY CASE rating
    WHEN 'G' THEN 1
    WHEN 'PG' THEN 2
    WHEN 'PG-13' THEN 3
    WHEN 'R' THEN 4
    WHEN 'NC-17' THEN 5
END;
//结果
+---------+-----------------------------+--------+
| film_id | title                       | rating |
+---------+-----------------------------+--------+
|       2 | ACE GOLDFINGER              | G      |
|       4 | AFFAIR PREJUDICE            | G      |
...
|       1 | ACADEMY DINOSAUR            | PG     |
|       6 | AGENT TRUMAN                | PG     |
...
|       7 | AIRPLANE SIERRA             | PG-13  |
|       9 | ALABAMA DEVIL               | PG-13  |
...
|       8 | AIRPORT POLLOCK             | R      |
|      17 | ALONE TRIP                  | R      |
...
|       3 | ADAPTATION HOLES            | NC-17  |
|      10 | ALADDIN CALENDAR            | NC-17  |
...
1000 rows in set (0.00 sec)

使用 CASE 将电影的等级转换为一个索引数字。然后使用 ORDER BY 按照这个数字进行排序。

CASE 子句写起来很复杂,特别是列表值很多的时候。可以使用如下的 FIELD() 函数。

SELECT * FROM film ORDER BY FIELD(rating, 'G', 'PG', 'PG-13', 'R', 'NC-17');

ORDER BY 和 NULL:

在 MySQL 中使用 ORDER BY 子句升序 ASC 排序时, NULL 值会出现在非 NULL 值之前。

在 MySQL 中使用 ORDER BY 子句降序DESC排序时, NULL 值会出现在非 NULL 值之后

1.1.13. LIMIT

LIMIT 子句可以设置 SELECT 语句返回固定行的数据,接收一个或两个非负数作为参数。

LIMIT和ORDER BY子句:

SELECT 语句中, LIMIT 子句经常和 ORDER BY子句结合使用。比如在下面的场景中:

    • ERP 中显示销售额最高的 5 个销售员
    • 网站上的点击率最高的 10 个文章
    • 论坛中一个月内最活跃的 10 个会员
    • 博客网站的文章分页列表

这些场景中,先按照某个规则排序,然后使用取出指定数量的记录行。

MySQL LIMIT 实例:

查询片长最长的10部影片:

SELECT 
    film_id, title, length
FROM
    film
WHERE
    reting = 'G'
ORDER BY length DESC
LIMIT 10;
//查询结果
+---------+--------------------+--------+
| film_id | title              | length |
+---------+--------------------+--------+
|     212 | DARN FORRESTER     |    185 |
|     182 | CONTROL ANTHEM     |    185 |
|     609 | MUSCLE BRIGHT      |    185 |
|     597 | MOONWALKER FOOL    |    184 |
|     128 | CATCH AMISTAD      |    183 |
|     996 | YOUNG LANGUAGE     |    183 |
|      50 | BAKED CLEOPATRA    |    182 |
|     467 | INTRIGUE WORST     |    181 |
|     510 | LAWLESS VISION     |    181 |
|     612 | MUSSOLINI SPOILERS |    180 |
+---------+--------------------+--------+

使用 LIMIT 子句进行分页:

对于一些大型的数据表来说,分页查询能很好的减少数据库的消耗和提高用户体验。如果一个表中有1万条数据,不进行分页查询所有数据都显示在页面上,会发生以下问题:

    • 增加数据库的性能消耗
    • 传输过程中的数据量增加
    • 用户的体验不好,太多的数据对让用户眼花缭乱。

引入分页后,每页显示 10 行数据, 1万行数据需要 1000 (10000 / 10) 页就能显示完全。

要查询第二页数据需要先跳过第一页的 10 行数据并且最多行数为 10 行数据,整个 SQL 如下:

SELECT film_id, title FROM film LIMIT 10, 10;

//结果
+---------+------------------+
| film_id | title            |
+---------+------------------+
|       1 | ACADEMY DINOSAUR |
|       2 | ACE GOLDFINGER   |
|       3 | ADAPTATION HOLES |
|       4 | AFFAIR PREJUDICE |
|       5 | AFRICAN EGG      |
|       6 | AGENT TRUMAN     |
|       7 | AIRPLANE SIERRA  |
|       8 | AIRPORT POLLOCK  |
|       9 | ALABAMA DEVIL    |
|      10 | ALADDIN CALENDAR |
+---------+------------------+

1.1.14. DISTINCT

使用 SELECT 查询数据时,会有一些重复的行。比如演员表中有很多重复的姓氏。如果想得到一个唯一的、没有重复记录的结果集,就需要在SELECT后面加上 DISTINCT 关键字就能返回一个没有重复记录行的结果集。

MySQL DISTINCT 实例:

DISTINCT 可以消除多个字段的重复值。当指定多个字段值时, DISTINCT 使用多个字段组合确定记录行的唯一性。检索 actor 表中的名字和姓氏:

SELECT DISTINCT last_name, first_name FROM actor;
//结果
+--------------+-------------+
| last_name    | first_name  |
+--------------+-------------+
| GUINESS      | PENELOPE    |
| WAHLBERG     | NICK        |
| CHASE        | ED          |
| DAVIS        | JENNIFER    |
| LOLLOBRIGIDA | JOHNNY      |
...
| TEMPLE       | THORA       |
+--------------+-------------+
199 rows in set (0.01 sec)

注意:DISTINCT 关键字确保了查询结果中的每个值都是唯一的,但它并不会删除表中的任何数据,仅在结果集中消除了重复的行。

DISTINCT 与 NULL:

DISTINCT 遇到 NULL 值时,只保留一个 NULL 值。因为 DISTINCT 认为所有的 NULL 值都是相同的,这与字段的类型无关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值