【问题标题】:Oracle SQL to delete duplicate records based on columnsOracle SQL 根据列删除重复记录
【发布时间】:2025-12-13 20:20:04
【问题描述】:

我有一个记录表:

DATE           NAME    AGE    ADDRESS
01/13/2014     abc     27     us
01/29/2014     abc     27     ma            <- duplicate
02/03/2014     abc     27     ny            <- duplicate
02/03/2014     def     28     ca

我想删除记录号 2 和 3,因为它们是基于名称和年龄的记录 1 的重复项。 DATE 列是基于添加时记录的时间戳(sql 日期)并被认为是唯一的。

我找到了这个 sql,但不确定它是否会起作用,并且有点担心,因为该表有 200 万条记录,删除错误的记录是个坏主意:

SELECT A.DATE, A.NAME, A.AGE
  FROM table A
 WHERE EXISTS (SELECT B.DATE
             FROM table B
            WHERE B.NAME = A.NAME
          AND B.AGE = A.AGE);

这条记录的实例很多,如果有人可以帮我写一个sql来删除这条记录?

【问题讨论】:

  • 你真正在使用哪个DBMS???
  • 在标题中,您将 oracle、mysql 和 sql-server 作为标签。你真正想要哪一个?
  • 我正在使用 oracle sql developer 查看表。刚看到sql语句不知道能不能用。

标签: sql oracle


【解决方案1】:

查询

DELETE FROM tbl t1
WHERE dt IN 
(
  SELECT t1.dt
  FROM   tbl t1
  JOIN   tbl t2 ON 
  (
    t2.name = t1.name
    AND t2.age=t1.age
    AND t2.dt > t1.dt
  )
);

Fiddle demo

【讨论】:

    【解决方案2】:
    delete from table 
     where (date, name, age) not in ( select max( date ), name, age from table group by name, age )
    

    删除前验证

    select * from table 
     where (date, name, age) not in ( select max( date ), name, age from table group by name, age ) 
    

    【讨论】:

      【解决方案3】:

      ROW_NUMBER解析函数会有帮助(Oracle和Sqlserver支持)。
      需要在 ORDER BY 子句中仔细实现为分区内的每一行分配唯一有序号的逻辑。

      SELECT A_TABLE.*,
              ROW_NUMBER ()
              OVER (PARTITION BY NAME, AGE
                    ORDER     BY DATE  DESC)
                 seq_no
      FROM A_TABLE;
      

      然后您可以将结果用于删除操作:

      Delete A_TABLE 
      where DATE,NAME,AGE IN 
      (
         SELECT DATE,NAME,AGE FROM
         (
            SELECT A_TABLE.*,
                  ROW_NUMBER ()
                  OVER (PARTITION BY NAME, AGE
                    ORDER     BY DATE DESC)
                     seq_no
            FROM A_TABLE;
         ) 
         WHERE seq_no != 1
       )    
      

      【讨论】: