oracle 如何基于所有列选择/删除所有重复行

06odsfpq  于 2022-11-28  发布在  Oracle
关注(0)|答案(2)|浏览(138)

我想选择/删除多个表中的所有重复行。我在互联网上搜索线索,但我看到的都是基于一个或多个列选择重复行的查询。如下所示:SELECT col1 count(*) from table_name group by col1 having count(*) > 1
我想要实现的是基于ALL COLUMNS选择重复的行,只要它们在每列中的所有值都相同。
我正在处理多个表,所以我希望它是通用的,这样它就可以在任何表上工作。

olmpazwi

olmpazwi1#

如果要删除重复项并保留每一行的第一个示例,则可以在ROWID伪列上的delete和correlate中使用子查询,并在每个组中查找ROW_NUMBER大于1的行:

DELETE FROM table_name
WHERE ROWID IN (
  SELECT ROWID
  FROM   (
    SELECT ROW_NUMBER() OVER (
             PARTITION BY col1, col2, col3, /*...,*/ colN -- List all the columns
             ORDER BY ROWID
           ) AS rn
    FROM   table_name
  )
  WHERE  rn > 1
);

如果要删除所有重复项的所有副本,请执行以下操作:

DELETE FROM table_name
WHERE ROWID IN (
  SELECT ROWID
  FROM   (
    SELECT COUNT(*) OVER (
             PARTITION BY col1, col2, col3, /*...,*/ colN -- List all the columns
           ) AS cnt
    FROM   table_name
  )
  WHERE  cnt > 1
);
nfeuvbwi

nfeuvbwi2#

我采用了MTO的答案,并做了一些更正和更通用的

declare
      l_column_list varchar2(32767);
      l_table_name  varchar2(4000) := 'AAAA_DATES';
    begin
      for rec in (select column_name, column_id
                    from dba_tab_cols
                   where table_name = l_table_name
                   order by column_id) loop
        if (rec.column_id = 1) then
          l_column_list := rec.column_name;
        else
          l_column_list := l_column_list || ',' || rec.column_name;
        end if;
      end loop;

      execute immediate 'DELETE FROM ' || l_table_name ||
                        '  WHERE ROWID IN (
      SELECT ROW_id
      FROM   (
        SELECT rowid row_id, ROW_NUMBER() OVER (
                 PARTITION BY ' || l_column_list ||
                        ' ORDER BY ROWNUM
               ) AS rn
        FROM ' || l_table_name || '
      )
      WHERE  rn > 1
    )';
      dbms_output.put_line(sql%rowcount);
      commit;
    end;

相关问题