【问题标题】:How to delete duplicates based off a composite key without using merge如何在不使用合并的情况下根据复合键删除重复项
【发布时间】:2019-04-03 18:31:07
【问题描述】:

因此,我目前遇到一个问题,即在尝试从物化视图插入表时,我遇到了基于 复合键 的重复项。 复合键由三列组成:TIMESTAMP、NAME 和 TYPE。我尝试使用以下方法,但仍然遇到相同的问题(我收到重复的错误消息并且存储过程停止运行)。有没有办法处理异常,以便它跳过重复的行?如果不是我想到了下面的 DELETE 语句来消除重复项,这是正确的方法吗?

以下是我正在使用的“批量插入”语句:

DELETE FROM table
     where timestamp IN (SELECT DISTINCT ts from mv_1)
       and person IN (SELECT distinct name from mv_1)
       and TYPE IN (SELECT distinct data_type from mv_1);
       commit;
--
 DELETE FROM table
     WHERE    timestamp || person || TYPE IN
              (SELECT DISTINCT
                         ts
                      || name
                      || data_type
                 FROM edb.mv_1); 
COMMIT;
--
INSERT INTO table
           (person
            timestamp,
            TYPE)
  SELECT name,
         ts,
         data_type
    FROM edb.mv_1 a
   WHERE  a.row_id NOT IN
                (SELECT row_id
                   FROM (SELECT v.*,
                                ROW_NUMBER ()
                                OVER (
                                   PARTITION BY v.name,
                                                v.data_type,
                                                v.ts
                                   ORDER BY row_id)
                                   AS rn
                           FROM mv_1 v) t
                  WHERE rn > 1)

注意: row_id 是我在 MV_1 中创建的一列,这样我就有一列可以给我一个唯一的标识符。

提前致谢!

【问题讨论】:

  • 问题实际上是因为mv_1 中的复合键组合已经存在于目标表中吗?还是因为mv_1 中有重复项?在您的第二种删除类型中使用 distinct 暗示后者。 (还有distinctin() 有点毫无意义)。如果您确实有重复的密钥,您如何决定保留哪个? (另外,要真正解决您关于跳过行的问题:是的;DML error logging。)
  • 感谢您的回复@AlexPoole。我想插入/保留最新值。复合键存在于目标表中,但不存在于物化视图 (MV_1) 中。有两种情况会发生重复 1) 实际上在 MV_1 中重复 2) 该特定复合键已经存在的记录(如果有意义的话)。

标签: sql oracle duplicates sql-delete


【解决方案1】:

我会通过添加复合主键(您肯定已经这样做了)来使表安全:

ALTER TABLE table ADD CONSTRAINT pk_table PRIMARY KEY (timestamp, person, type);

此外,我还会通过在其中添加主键来确保物化视图的安全。根据 mv ist 的构建方式,您需要更改提供它的查询,以免出现重复。参见例如here

如果两者都是安全的,则插入很简单:

INSERT INTO table (timestamp, person, type, further_col1, col2, ...)
SELECT timestamp, name, type, further_col1, col2, ....
  FROM edb.mv_1 m
 WHERE NOT EXISTS (
       SELECT * 
         FROM table t2 
        WHERE t2.timestamp = m.timestamp
          AND t2.person    = m.name
          AND t2.type      = m.type
       );

如果您只有三列,则可以将插入缩短为:

INSERT INTO table (timestamp, person, type)
SELECT timestamp, name  , type FROM edb.mv_1  
MINUS
SELECT timestamp, person, type FROM table;  

请确保表和 mv 中的列不为 NULL。请不要命名表table 和列timestamptype。我确信它们只是示例。

【讨论】:

    猜你喜欢
    • 2015-06-14
    • 2023-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    • 2014-08-26
    相关资源
    最近更新 更多