SQL 删除重复项

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

SQL 删除重复项 问题描述

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

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

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

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

select distinct job
  from emp

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

select job
  from emp
 group by job

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

每一行都被分配了一个递增的序号,当职位种类发生改变时,序号也会被重置为 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

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

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程