查询语句有可能会返回重复的数据,我们可以使用 DISTINCT 关键字排除查询结果中的重复记录。
本文比较五种主流数据库排除重复查询结果的实现和差异,包括 MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLite。
排除重复结果 | MySQL | Oracle | SQL Server | PostgreSQL | SQLite |
---|---|---|---|---|---|
DISTINCT | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
DISTINCTROW | ✔️ | ❌ | ❌ | ❌ | ❌ |
UNIQUE | ❌ | ✔️ | ❌ | ❌ | ❌ |
DISTINCT ON | ❌ | ❌ | ❌ | ✔️ | ❌ |
单个字段去重
以下语句查找员工表中的所有不同性别:
SELECT DISTINCT sex
FROM employee;
其中,DISTINCT 关键字位于 SELECT 之后,而不像其他过滤条件一样位于 WHERE 子句中。查询返回的结果如下:
sex
---
男
女
在 Oracle 数据库中,可以使用 UNIQUE 关键字替代 DISTINCT。例如:
SELECT UNIQUE sex
FROM employee;
在 MySQL 中,可以使用 DISTINCTROW 关键字替代 DISTINCT。例如:
SELECT DISTINCTROW sex
FROM employee;
多个字段去重
DISTINCT 也可以用于多个字段的去重。例如,以下语句查找不同部门编号和性别的所有组合:
SELECT DISTINCT dept_id, sex
FROM employee;
查询返回的结果如下:
dept_id|sex
-------|---1|男 2|男 3|女 4|男 4|女 5|男
除了 DISTINCT 之外,我们也可以使用 ALL 关键字返回不排除重复数据的结果。不过通常没有必要,因为使用 ALL 是默认的行为。例如:
SELECT ALL dept_id, sex
FROM employee;
部分字段去重
PostgreSQL 提供了一种扩展的去重语法:DISTINCT ON,可以基于部分字段返回不同的数据。例如:
SELECT DISTINCT ON (dept_id) dept_id, emp_name
FROM employee;dept_id|emp_name|
-------+--------+1|刘备 |2|诸葛亮 |3|孙尚香 |4|赵云 |5|法正 |
以上查询基于部门编号去重,每个部门只会返回一条记录,每个部门只返回第一个员工姓名。
如果指定了 ORDER BY,可以改变每个 DISTINCT ON 分组内的数据顺序。例如:
SELECT DISTINCT ON (dept_id) dept_id, emp_name
FROM employee
ORDER BY dept_id, emp_name;dept_id|emp_name|
-------+--------+1|关羽 |2|黄忠 |3|孙尚香 |4|关平 |5|邓芝 |