0

次の整数列で構成されるテーブルがあります。

group_id, person_id, sequence

理想的には、主キーは ですが(group_id, person_id)、最初に削除する必要がある重複がいくつかあります。重複がある場合は常に、最小のシーケンス値のみを保持したいと考えています。

誤った行の一部を選択するクエリを見つけましたが、重複セットで最大のシーケンス番号しか取得しません。

SELECT COUNT(*) AS num, group_id, person_id, MAX(sequence)
FROM my_table
GROUP BY group_id, person_id
HAVING COUNT(*) > 1;

私は単純なものが欠けていると確信しています。これらの重複を簡単に削除する方法はありますか?

ありがとう。

4

2 に答える 2

0

すべての列が重複している必要があります。したがって、このようにすべての列を適用してグループ化します

select * from my_table where not EXISTS (
    SELECT group_id, person_id, min(sequence)
    FROM my_table
    GROUP BY group_id, person_id
    HAVING COUNT(*) > 1);
于 2015-07-07T04:34:10.287 に答える
0

削除する行を返すクエリを作成してみてください。(group_id,person_id,sequence)の組み合わせが UNIQUE で、NULL 値がないと仮定すると...

 SELECT t.* 
   FROM my_table t
   JOIN ( SELECT o.group_id
               , o.person_id
               , MAX(o.sequence) AS max_sequence
            FROM my_table o
           GROUP BY o.group_id, o.person_id
          HAVING COUNT(*) > 1
        ) d
    ON d.group_id      = t.group_id
   AND d.person_id     = t.person_id
   AND d.max_sequence  = t.sequence

キーワードをキーワードにDELETE置き換えることで、それをステートメントに変換できます。SELECTDELETE

または、これに似たステートメントで行を削除する場合、通常、削除する行の「バックアップ」としてテーブルを作成します。

SELECT の前にCREATE TABLE some_new_table_name AS.

次に、DELETE クエリで「保存された」行を参照できます。

DELETE t.*
  FROM my_table t
  JOIN some_new_table_name d
    ON d.group_id      = t.group_id
   AND d.person_id     = t.person_id
   AND d.max_sequence  = t.sequence

このアプローチは、重複の「1」のみを取得します。元のクエリのカウント値が 2 より大きい場合、これを十分な回数繰り返す必要があります。そのたびに最大のシーケンス値を削除し、1 より大きいカウント値がなくなるまでそれを繰り返します。

削除する重複が多数ある場合は、わずかに異なるパターンを使用して、それらを一気に取得できます。

MAX(sequence)(削除したい行) を返す代わりに、MIN(sequence)保持したい行を返すことができます。そして、述語を変更します。

    AND d.max_sequence  = t.sequence

することが

    AND d.min_sequence  <> t.sequence

そのため、最小値を持つ行を除いて、そのすべての行を削除します。group_id, person_id

ステートメントSELECTに変換する前に、これを最初に書くことを強くお勧めします。DELETEまた、テーブルの適切なバックアップを作成するか、削除する行のコピーを「保存」することをお勧めします。いくつかの行を復元する必要がある場合に備えて。

于 2015-07-07T04:47:10.610 に答える