代码之家  ›  专栏  ›  技术社区  ›  John Wick

如何在不使用合并的情况下删除基于复合键的重复项

  •  0
  • John Wick  · 技术社区  · 7 年前

    所以我现在遇到了一个问题,我遇到了基于 复合密钥 试图从物化视图插入表时。这个 复合密钥 由三列组成: 时间戳、名称和类型 .我尝试过使用以下方法,但仍然遇到相同的问题(我收到了重复的错误消息,存储过程停止运行)。有没有办法处理异常,使其跳过重复的行?如果不是,我想到了下面的删除语句来消除重复项,这是正确的方法吗?

    以下是我使用的“批量插入”声明:

    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中创建的一个列,这样我就有了一个可以给我唯一标识符的列。

    提前谢谢!

    1 回复  |  直到 7 年前
        1
  •  0
  •   wolφi    7 年前

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

    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中的E列不为空。请不要给表格命名 table 和专栏 timestamp type .我相信这些只是例子。