SQL 删除重复项

SQL 删除重复项,你想找出 EMP 表里不同的职位种类,但又不希望看到重复项。结果集应该如下所示。

SQL 删除重复项 问题描述

你想找出 EMP 表里不同的职位种类,但又不希望看到重复项。结果集应该如下所示。

JOB
---------
ANALYST
CLERK
MANAGER
PRESIDENT
SALESMAN
SQL

SQL 删除重复项 解决方案

所有的关系数据库管理系统都支持 DISTINCT 关键字,并且它也是从结果集中删除重复项的最简单的方法。然而,本实例将展示另外两种删除重复项的做法。
DB2、Oracle 和 SQL Server
传统的做法是使用 DISTINCT,有时候也会用 GROUP BY(正如后面的 MySQLPostgreSQL 解决方案),这些方法适用于所有的关系数据库管理系统。下面给出的替代解决方案则使用了窗口函数 ROW_NUMBER OVER

1  select job
2    from (
3  select job,
4         row_number()over(partition by job order by job) rn
5    from emp
6         )x
7   where rn = 1

SQL

MySQLPostgreSQL
使用 DISTINCT 关键字从结果集里删除重复项。

select distinct job
  from emp

SQL

另外,也可以通过 GROUP BY 达到同样目的。

select job
  from emp
 group by job
SQL

SQL 删除重复项 扩展知识

DB2、Oracle 和 SQL Server
本解决方案展示了一种分区窗口函数(partitioned window function)的特殊用法。通过在 OVER 子句里使用 PARTITION BY,当一种新的职位出现时,ROW_NUMBER 的返回值会被重置为 1。内嵌视图 X 的结果集如下所示。

select job,
       row_number()over(partition by job order by job) rn
  from emp
 
JOB               RN
--------- ----------
ANALYST            1
ANALYST            2
CLERK              1
CLERK              2
CLERK              3
CLERK              4
MANAGER            1
MANAGER            2
MANAGER            3
PRESIDENT          1
SALESMAN           1
SALESMAN           2
SALESMAN           3
SALESMAN           4
SQL

每一行都被分配了一个递增的序号,当职位种类发生改变时,序号也会被重置为 1。为了删除重复项,我们需要筛选出 RN 等于 1 的那些行。
使用 ROW_NUMBER OVER 时,必须有一个 ORDER BY 子句(DB2 除外),但这并不影响最终结果。我们只是希望提取出每一种职位,至于每一个职位来自哪一行其实无关紧要。
MySQL 和 PostgreSQL
第一种解决方案展示了如何使用关键字 DISTINCT 从结果集里删除重复项。需要注意的是,DISTINCT 会对整个 SELECT 列表做限制;增加一列或者几列会改变最终的结果集。考虑下面两个查询的差异。

select distinct job          select distinct job, deptno
  from emp                     from emp
 
JOB                            JOB           DEPTNO
---------                      --------- ----------
ANALYST                        ANALYST           20
CLERK                          CLERK             10
MANAGER                        CLERK             20
PRESIDENT                      CLERK             30
SALESMAN                       MANAGER           10
                               MANAGER           20
                               MANAGER           30
                               PRESIDENT         10
                               SALESMAN          30
SQL

SELECT 列表里增加 DEPTNO 列的话,返回的就变成了 EMP 表里不同的 JOB/DEPTNO 组合值。
第二种解决方案使用 GROUP BY 删除重复项,以这种方式使用 GROUP BY 并不罕见。注意,GROUP BYDISTINCT 是两个非常不同的子句,它们是不可互换的。为了给出全部可行的解决方案,我特地把使用 GROUP BY 去掉重复项的做法也包含进了本实例,这样读者下次看到类似做法时就不会有什么疑问了。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程