MySQL DISTINCT 用法和实例

本文介绍了如何在 MySQL 中的 SELECT 语句中使用 DISTINCT 关键字去除结果集中的重复行。

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

MySQL DISTINCT 用法

SELECT 语句中使用 DISTINCT 关键字会返回一个没有重复记录行的结果集。 DISTINCT 的用法如下:

SELECT DISTINCT
    columns_list
FROM
    table_name

说明:

  • DISTINCT 关键字位于 SELECT 关键字的后面。
  • columns_list 指定要查询的字段列表,也是 DISTINCT 评估记录行是否唯一的字段。
  • columns_list 可以是一个字段,也可以是多个字段。
  • columns_list 也可以是 *

MySQL DISTINCT 实例

在以下实例中,我们使用 Sakila 示例数据库中的 actor进行演示。

DISTINCT 单个字段

姓氏重复是一个很正常的现象。我们先使用 SELECT 语句检索以下 actor 表中的姓氏。

SELECT last_name FROM actor;
+--------------+
| last_name    |
+--------------+
| AKROYD       |
| AKROYD       |
| AKROYD       |
| ALLEN        |
| ALLEN        |
...
| ZELLWEGER    |
| ZELLWEGER    |
+--------------+
200 rows in set (0.01 sec)

然后我们使用 DISTINCT 删除重复的数据,返回唯一的姓氏列表:

SELECT DISTINCT last_name FROM actor;
+--------------+
| last_name    |
+--------------+
| AKROYD       |
| ALLEN        |
| ASTAIRE      |
| BACALL       |
| BAILEY       |
...
| ZELLWEGER    |
+--------------+
121 rows in set (0.00 sec)

我们可以看到输出的结果集中已经没有了重复数据。结果集的行数也从原来的 200 行变成了 121 行。

DISTINCT 多个字段

DISTINCT 还可以清除多个字段的重复值。当指定多个字段值时, DISTINCT 使用多个字段组合确定记录行的唯一性。

现实中,我们不但存在姓氏重复的情况,名字也可能重复。我们检索 actor 表中的名字和姓氏:

SELECT last_name, first_name FROM actor;
+--------------+-------------+
| last_name    | first_name  |
+--------------+-------------+
| GUINESS      | PENELOPE    |
| WAHLBERG     | NICK        |
| CHASE        | ED          |
| DAVIS        | JENNIFER    |
| LOLLOBRIGIDA | JOHNNY      |
| NICHOLSON    | BETTE       |
...
| TEMPLE       | THORA       |
+--------------+-------------+
200 rows in set (0.01 sec)

然后我们使用 DISTINCT 删除重复的数据:

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)

我们可以看到输出结果集的行数也从原来的 200 行变成了 199 行。这说明原来的结果集中有一行重复记录。我们通过以下的分组汇总语句也能证明这一点:

SELECT last_name, first_name, COUNT(*)
FROM actor
GROUP BY last_name , first_name
HAVING COUNT(*) > 1;
+-----------+------------+----------+
| last_name | first_name | COUNT(*) |
+-----------+------------+----------+
| DAVIS     | SUSAN      |        2 |
+-----------+------------+----------+
1 row in set (0.00 sec)

注意: 上面的 SQL 语句使用了 GROUP BY, HAVING, COUNT() 对数据进行了分组汇总。

DISTINCT 与 NULL

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

例如下面的 SQL 使用返回多行 NULL 记录:

SELECT *
FROM (
    SELECT NULL
    UNION ALL
    SELECT NULL
    UNION ALL
    SELECT NULL
  ) t;
+------------+
| NULL       |
+------------+
| NULL       |
| NULL       |
| NULL       |
+------------+
3 rows in set (0.00 sec)

当使用 DISTINCT 之后:

SELECT DISTINCT *
FROM (
    SELECT NULL
    UNION ALL
    SELECT NULL
    UNION ALL
    SELECT NULL
  ) t;
+------------+
| NULL       |
+------------+
| NULL       |
+------------+
1 row in set (0.00 sec)

本例使用 UNION 关键字模拟包含多个 NULL 记录值的记录集。

结论

本文介绍了在 MySQL 中如何使用 DISTINCT 子句清除结果集中的重复记录行。 DISTINCT 子句的用法要点如下:

  • DISTINCT 清除 SELECT 结果集中的重复记录行。
  • DISTINCT 可以用一个字段或者多个字段,也可以用 *
  • DISTINCT 多个 NULL 值只保留一个 NULL 值。