SQL 删除重复数据,你正在生成一个报表,当相邻两行的某列出现了相同值时,你希望那个值只显示一次。例如,你想从 EMP
表中提取出 DEPTNO
和 ENAME
,希望按照 DEPTNO
对所有的行进行分组,并且希望每个 DEPTNO
只显示一次。你希望返回如下所示的结果集。
SQL 删除重复数据 问题描述
你正在生成一个报表,当相邻两行的某列出现了相同值时,你希望那个值只显示一次。例如,你想从 EMP
表中提取出 DEPTNO
和 ENAME
,希望按照 DEPTNO
对所有的行进行分组,并且希望每个 DEPTNO
只显示一次。你希望返回如下所示的结果集。
SQL 删除重复数据 解决方案
这是一个很简单的格式化问题,Oracle 提供的窗口函数 LAG OVER
能很容易地解决这一问题。当然,使用标量子查询和其他窗口函数也能达到同样目的(对于非 Oracle 用户只能如此),但这里最方便的做法是使用 LAG OVER
函数。
DB2 和 SQL Server
使用窗口函数 MIN OVER
为每个 DEPTNO
找出最小的 EMPNO
,然后使用 CASE
表达式来“涂改”那些 EMPNO
不等于该最小值的行。
Oracle
使用窗口函数 LAG OVER
访问当前行的前一行,为每个分区间找出第一个 DEPTNO
。
PostgreSQL 和 MySQL
本实例着重介绍如何使用窗口函数方便地访问到当前行前面和后面的行数据。在写作本书时,这些数据库尚未支持这类窗口函数。
SQL 删除重复数据 扩展知识
DB2 和 SQL Server
首先,使用窗口函数 MIN OVER
找出每个 DEPTNO
对应的最小 EMPNO
值。
下一步也是最后一步,使用 CASE
表达式删除重复的 DEPTNO
。如果一个员工的 EMPNO
和 MIN_EMPNO
相等,则返回 DEPTNO
,否则返回 Null
。
Oracle
首先,使用窗口函数 LAG OVER
为每一行返回前一行的 DEPTNO
。
如果仔细观察以上结果集的话,很容易区分出哪些行的 DEPTNO
和 LAG_DEPTNO
相等。对于这些行,我们希望把 DEPTNO
显示为 Null
。我们可以借助 DECODE
函数做到这一点(TO_NUMBER
函数可以把 DEPTNO
转换为数字)。