【问题标题】:Delete duplicate records using rownum in sql在sql中使用rownum删除重复记录
【发布时间】:2014-01-11 19:47:59
【问题描述】:

请帮助我了解基于 rownum 的删除记录,即使 id 重复也不会发生,但如果是这样的话。

select rownum,a.* from a;

    ROWNUM         ID NAME
---------- ---------- ----------
         1          1 leo_1
         2          2 leo_2
         3          3 leo_3
         4          1 leo_1
         5          2 leo_2
         6          3 leo_3

查询已尝试,但删除了所有 6 行。

DELETE FROM a
WHERE rownum not in
(SELECT MIN(rownum)
FROM a
GROUP BY name);

但是这个查询给出了正确的结果:

SELECT MIN(rownum)
FROM a
GROUP BY name

    ROWNUM
----------
         1
         2
         3

预期结果:

    ROWNUM         ID NAME
---------- ---------- ----------
         4          1 leo_1
         5          2 leo_2
         6          3 leo_3

【问题讨论】:

  • 预期结果是哪个查询的结果?
  • 感谢您的所有回答。

标签: sql oracle


【解决方案1】:

使用rowid

DELETE FROM table_name a
 WHERE EXISTS( SELECT 1
                 FROM table_name b
                WHERE a.id = b.id
                  AND a.name = b.name
                  AND a.rowid > b.rowid )

当然,您也可以使用a.rowid < b.rowidrowid 只是该行的物理地址,因此无论您删除地址较大还是较小的行都没有关系。

但是,您的预期结果没有意义。

Expected Result :

        ROWNUM         ID NAME
    ---------- ---------- ----------
             4          1 leo_1
             5          2 leo_2
             6          3 leo_3

结果集的rownum 总是在查询时分配。这意味着特定行可能会在不同的查询中出现不同的rownum 值(或者当同一查询运行多次时)。 rownum 始终是连续的,因此您永远不能在结果集中拥有 4 的 rownum 而在同一结果集中也没有 rownum 值 1、2 和 3。无论您删除哪个重复行,您的结果都是

预期结果:

    ROWNUM         ID NAME
---------- ---------- ----------
         1          1 leo_1
         2          2 leo_2
         3          3 leo_3

但是rownum 的值是任意的。甲骨文返回同样有效

预期结果:

    ROWNUM         ID NAME
---------- ---------- ----------
         1          2 leo_2
         2          3 leo_3
         3          1 leo_1

【讨论】:

    【解决方案2】:
    DELETE FROM a
    WHERE rowid not in
    (SELECT MIN(rowid) FROM a group BY name);
    

    【讨论】:

    • 在查询执行时分配给每一行的行号。Rownum 是临时的,但 rowid 是永久的
    • 如果其他人在没有 RowId 的情况下设计了这个?
    【解决方案3】:
    delete from tb_test where c1 in (select c1 from (select c1,c2, 
    row_number() over (partition by c2 order by c2)  rn
    from tb_test) a where a.rn >1 );
    

    C1为主键列,c2为重复值列。

    【讨论】:

      猜你喜欢
      • 2021-07-18
      • 2016-01-07
      • 2016-09-17
      • 1970-01-01
      • 2020-07-16
      • 2021-02-13
      • 1970-01-01
      • 2010-10-24
      相关资源
      最近更新 更多