在单个查询中从DB2中的表中删除重复的行

Vic*_*cky 7 sql db2 sql-delete

我有一个包含3列的表格如下:

one   |   two    |  three  |   name
------------------------------------
 A1       B1          C1        xyz
 A1       B1          C1        pqr      -> should be deleted
 A1       B1          C1        lmn      -> should be deleted
 A2       B2          C2        abc
 A2       B2          C2        def      -> should be deleted
 A3       B3          C3        ghi
------------------------------------ 
Run Code Online (Sandbox Code Playgroud)

该表没有任何主键列.我对表没有任何控制权,因此我无法添加任何主键列.

如图所示,我想删除一列,两列和三列组合相同的行.因此,如果A1B1C1发生三次(如上所述),则应删除其他两个,只留下一个.

如何通过DB2中的一个查询实现这一目标?

我的要求是单个查询,因为我将通过java程序运行它.

bha*_*mby 21

(这假设您使用的是DB2 for Linux/Unix/Windows,其他平台可能略有不同)

DELETE FROM
    (SELECT ROWNUMBER() OVER (PARTITION BY ONE, TWO, THREE) AS RN
     FROM SESSION.TEST) AS A
WHERE RN > 1;
Run Code Online (Sandbox Code Playgroud)

应该得到你想要的东西.

该查询使用OLAP功能 ROWNUMBER()分配一个号码为每个内的每个行ONE,TWO,THREE组合.然后,DB2可以将fullselect(A)引用的行与该DELETE语句应从表中删除的行进行匹配.为了能够使用a fullselect作为delete子句的目标,它必须匹配可删除视图的规则(请参阅注释部分下的"删除视图").

下面是一些证明(在LUW 9.7上测试):

DECLARE GLOBAL TEMPORARY TABLE SESSION.TEST (
    one CHAR(2),
    two CHAR(2),
    three CHAR(2),
    name CHAR(3)
) ON COMMIT PRESERVE ROWS;

INSERT INTO SESSION.TEST VALUES 
    ('A1', 'B1', 'C1', 'xyz'),
    ('A1', 'B1', 'C1', 'pqr'),
    ('A1', 'B1', 'C1', 'lmn'),
    ('A2', 'B2', 'C2', 'abc'),
    ('A2', 'B2', 'C2', 'def'),
    ('A3', 'B3', 'C3', 'ghi');

DELETE FROM
    (SELECT ROWNUMBER() OVER (PARTITION BY ONE, TWO, THREE) AS RN
     FROM SESSION.TEST) AS A
WHERE RN > 1;

SELECT * FROM SESSION.TEST;
Run Code Online (Sandbox Code Playgroud)

2017年3月2日编辑:

在回答Ahmed Anwar的问题时,如果您需要捕获已删除的内容,您还可以将删除与" 数据更改语句 " 结合起来.在这个例子中,您可以执行以下操作,它将为您提供" rn "列,一个,两个三个:

SELECT * FROM OLD TABLE (
    DELETE FROM
        (SELECT 
             ROWNUMBER() OVER (PARTITION BY ONE, TWO, THREE) AS RN
            ,ONE
            ,TWO
            ,THREE
         FROM SESSION.TEST) AS A
    WHERE RN > 1
) OLD;
Run Code Online (Sandbox Code Playgroud)