【问题标题】:Delete duplicate records from a table oracle从表 oracle 中删除重复记录
【发布时间】:2019-11-25 23:21:05
【问题描述】:

我在如下表中有重复记录。


row no   name  eff_dt            address  pin
1             A       12-10-2007      AN         222
2             B       13-10-2007      AS         223
3             A        15-10-2007      AN        222
4             C        20-10-2007      AZ         222
5             C        27-10-2007      AZ         222
6             C        01-12-2007      AZ         222

我使用以下查询删除重复项:

delete from customer where rowid in(select rowid from(select rowid,name,eff_dt, address,pin, rownumber() over partition by name, address,pin order by eff_dt)rn from customer) where rn>1

查询从上表中删除了 rownum 3,5 和 6。

但是根据我的需要,rownum 3 不应该被删除,因为当我将它与 rownum 2 进行比较时它是不同的。但是它被查询删除了,因为它与 rownum 1 重复。

有没有办法以这种方式清除重复记录?就像只比较相邻的行? Name 和 eff_dt 是我的表的主键。

【问题讨论】:

  • 这里的“重复”是什么?
  • 嗨蒂姆..感谢您的回复..我正在比较姓名、地址和密码以检查重复项。

标签: sql oracle


【解决方案1】:

您可以根据您的要求使用以下查询删除重复项:

DELETE FROM CUSTOMER C
WHERE
    ROW_NO IN (
        SELECT
            ROW_NO
        FROM
            (
                SELECT
                    ROW_NO,
                    --
                    NAME,
                    LAG(NAME, 1) OVER(
                        ORDER BY
                            ROW_NO
                    ) LAG_NAME,
                    --
                    ADDRESS,
                    LAG(ADDRESS, 1) OVER(
                        ORDER BY
                            ROW_NO
                    ) LAG_ADDRESS,
                    --
                    PIN,
                    LAG(PIN, 1) OVER(
                        ORDER BY
                            ROW_NO
                    ) LAG_PIN
                    --
                FROM
                    CUSTOMER
            )
        WHERE
            NAME = LAG_NAME
            AND ADDRESS = LAG_ADDRESS
            AND PIN = LAG_PIN
    )

db<>fiddle demo

干杯!!

【讨论】:

    【解决方案2】:

    假设您想保留最早 eff_dt 的记录,我们可以尝试使用 EXISTS 子句进行删除:

    DELETE
    FROM customer c1
    WHERE EXISTS (SELECT 1 FROM customer c2
                  WHERE c1.name = c2.name AND
                        c1.address = c2.address AND
                        c1.pin = c2.pin AND
                        c2.eff_dt < c1.eff_dt);
    

    【讨论】:

    • 这将删除第 3 行,即使 OP 说他们只想与前一行进行比较并且不应删除第 3 行。
    • @MT0 问题下的第二条评论支持我回答中的逻辑。
    • OP 明确指出“但根据我的需要,rownum 3 不应该被删除,因为当我将它与 rownum 2 进行比较时它是不同的。但它被查询删除了,因为它是重复的关于 rownum 1. 有没有办法以这种方式清除重复记录?只比较相邻的行?"
    【解决方案3】:
    delete  from customer where rowid in(
    select rowid from (
    select rowid,name,eff_dt, address,pin, NAME||'--'||ADDRESS|| '--'||PIN as curnt,
    LAG(NAME||'--'||ADDRESS|| '--'||PIN , 1, 0) OVER (ORDER BY rowid asc) AS prev
    from customer)
    where curnt=prev);
    

    信息: https://oracle-base.com/articles/misc/lag-lead-analytic-functions

    【讨论】:

    • 当你有一行name = 'A', address = 'AAN', pin = 222 和相邻行name = 'AA', address = 'AN', pin = 222 时会发生什么?
    • 知道了。已编辑,这将是有效的。谢谢
    【解决方案4】:

    试试下面的 delete 语句,也许这就是你需要的。

    LAG(rowno, 1, NULL) OVER(按名称、地址、按 eff_dt 的引脚顺序分区)prev

    DELETE FROM customer a
     WHERE EXISTS 
             (SELECT 1
                FROM (SELECT ROWNO, NAME, EFF_DT, PIN, address,
                             row_number() over (partition by name, address, pin order by eff_dt) rownm,
                             LAG(rowno, 1, NULL) OVER (partition by name, address, pin order by eff_dt) prev
                        FROM customer) b
               WHERE rownm > 1
                 AND rowno - prev = 1
                 AND b.rowno = a.rowno)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-07
      • 2015-09-27
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      相关资源
      最近更新 更多