web-dev-qa-db-ja.com

単一の照会でDB2の表から重複行を削除する

以下のように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
------------------------------------ 

テーブルに主キー列がありません。テーブルを制御できないため、主キー列を追加できません。

示されているように、1列、2列、および3列の組み合わせが同じである行を削除したいと思います。したがって、A1B1C1が3回発生している場合(上記のように)、他の2つを削除し、1つだけを残す必要があります。

DB2で1つのクエリだけでこれを実現するにはどうすればよいですか?

Javaプログラムを介して実行するため、単一のクエリが必要です。

7
Vicky

(これは、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;
_

あなたが探しているものを手に入れるはずです。

クエリは OLAP関数ROWNUMBER()を使用して、各ONETWOTHREEの組み合わせ内の各行に番号を割り当てます。 DB2は、fullselect(A)によって参照される行を、 DELETEステートメント がテーブルから削除する必要がある行と一致させることができます。 fullselectを削除句のターゲットとして使用できるようにするには、 削除可能なビュー のルールに一致する必要があります(注セクションの「削除可能なビュー」を参照) 。

以下はいくつかの証拠です(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;
_

2017年3月2日編集:

Ahmed Anwarからの質問に答えて、削除されたものをキャプチャする必要がある場合は、削除を「 データ変更ステートメント 」と組み合わせることもできます。この例では、次のようなことを行うことができます。これにより、「rn」列、onetwo、およびthree

_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;
_
21
bhamby
DELETE FROM the_table tt
WHERE EXISTS ( SELECT *
    FROM the_table ex
    WHERE ex.one = tt.one
    AND ex.two = tt.two
    AND ex.three = tt.three
    AND ex.zname < tt.zname -- tie-breaker...
    );

注:SQL方言は異なる場合があります。注2:「名前」は一部のプラットフォームで予約語です。避けたほうがいいです。

2
wildplasser

@a_horse_with_no_nameのバリエーションは、groupby句とin句を使用せずにiseriesのdb2に回答します。それは実際に機能します

DELETE from the_table a 
where rrn(a) < (
select max(rrn(a)) from the_table b 
where a.one = b.one and a.two = b.two and a.three = b.three
)
1
danny117

非常に古いバージョンのdb2SQLを使用するその他の場合:これらの投稿の組み合わせは、2回投稿された2つのバッチから重複を識別して削除するのに役立ちました。

SELECT   * FROM     LIBRARY.TABLE a
WHERE    a.batch in (115131, 115287)
AND      EXISTS ( SELECT 1 from LIBRARY.TABLE d 
    WHERE d.batch in (115131, 115287)
     AND a.one = d.one AND a.two = d.two AND a.three = d.three 
    GROUP BY d.one, d.two, d.three 
    HAVING count(*) <> 1 )

    AND RRN(a) > (SELECT MIN(RRN(b)) FROM LIBRARY.TABLE b 
        WHERE b.batch in (115131, 115287)
        AND a.one = b.one AND a.two = b.two AND a.three = b.three );
0
Tom S.
Please take backup of table before deleting the data

Delete from table where Name in (select name from table
group by one,two,three
having count(*) > 2)

使用できます

     DELETE from TABLE Group by one,two,three Having count(*) > 2; 
0
Sunil Chavan
DELETE  FROM Table_Name
WHERE   Table_Name_ID NOT IN ( SELECT  MAX(Table_Name_ID)
                                    FROM    Table_Name
                                    GROUP BY one ,
                                             two, 
                                             three )

1つ2つ3つは繰り返される列であり、Table_Name_IDはPKです。

0
levi

これは、テーブルの主キーを必要としないlevenleviの回答のバリエーションです(現在、構文をテストすることはできません)

_DELETE FROM the_table
WHERE  rid_bit(the_table) NOT IN (SELECT MAX(rid_bit(the_table))
                                  FROM the_table
                                  GROUP BY one,two,three)
_

ISeriesではrid_bit()はサポートされていないと思いますが、rrn()は同じ目的を保存します