web-dev-qa-db-ja.com

2つの完全に同一の行の1つを削除するにはどうすればよいですか?

主キーなしでデータベーステーブルを削除しています(彼らは何を考えていたのかわかります)。主キーになる列に重複があるため、主キーを追加できません。重複する値は、すべての点で同一である2つの行の1つに由来します。主キー(または少なくともUQ NN列)のないテーブルでタスクを実行することを拒否するため、GUIを介して行を削除できません(この場合はMySQL Workbenchですが、データベースに依存しないアプローチを探しています)。主キーになる列に重複があるため、主キーを追加できません。重複する値は1つに由来します...

双子の1つを削除するにはどうすればよいですか?

31
david.libremone

問題を解決する1つのオプションは、同じスキーマで新しいテーブルを作成してから、次のことを行うことです。

INSERT INTO new_table (SELECT DISTINCT * FROM old_table)

次に、テーブルの名前を変更します。

もちろん、これを行うにはテーブルにディスク上のスペアが必要なのとほぼ同じ量のスペースが必要です!

効率的ではありませんが、信じられないほど簡単です。

21
Alnitak
SET ROWCOUNT 1
DELETE FROM [table] WHERE ....
SET ROWCOUNT 0

これは、2つの同一の行の1つのみを削除します

52
Rinaldo

MySQLにはDELETEの独自の拡張機能があります。これはDELETE ... LIMITであり、LIMITから期待される通常の方法で動作します。 http:// dev .mysql.com/doc/refman/5.0/en/delete.html

DELETEに対するMySQL固有のLIMIT row_countオプションは、制御がクライアントに返される前に削除される行の最大数をサーバーに伝えます。これは、特定のDELETEステートメントに時間がかかりすぎないようにするために使用できます。影響を受ける行の数がLIMIT値未満になるまで、DELETEステートメントを繰り返すだけです。

したがって、DELETE FROM some_table WHERE x="y" AND foo="bar" LIMIT 1;を使用できます。「1つを除くすべてを削除する」という簡単な方法はないことに注意してください。行の重複があるかどうかを確認し続けるだけです。

19
Piskvor

PostgreSQLの場合、これを行うことができます。

DELETE FROM tablename
WHERE id IN (SELECT id
          FROM (SELECT id, ROW_NUMBER() 
               OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum
               FROM tablename) t
          WHERE t.rnum > 1);

column1、column2、column3は、重複する値を持つ列セットです。

参照 ここ

10
Turbut Alin

delete top(1)は、Microsoft SQL Server(T-SQL)で機能します。

6
mattinsalto

これは、次のようにCTEとROW_NUMBER()関数を使用して実現できます。

/* Sample Data */
    CREATE TABLE #dupes (ID INT, DWCreated DATETIME2(3))

    INSERT INTO #dupes (ID, DWCreated) SELECT 1, '2015-08-03 01:02:03.456'
    INSERT INTO #dupes (ID, DWCreated) SELECT 2, '2014-08-03 01:02:03.456'
    INSERT INTO #dupes (ID, DWCreated) SELECT 1, '2013-08-03 01:02:03.456'

/* Check sample data - returns three rows, with two rows for ID#1 */
    SELECT * FROM #dupes 

/* CTE to give each row that shares an ID a unique number */
    ;WITH toDelete AS
      (
        SELECT ID, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DWCreated) AS RN
        FROM #dupes 
      )

  /* Delete any row that is not the first instance of an ID */
    DELETE FROM toDelete WHERE RN > 1

/* Check the results: ID is now unique */
    SELECT * FROM #dupes

/* Clean up */
    DROP TABLE #dupes

列をORDER BYにすると便利ですが、どの行を削除するかを選択する必要がない限り、必要ありません。これは、一度に1行ずつ削除するのではなく、重複レコードのすべてのインスタンスも処理します。

5
AHiggins

LIMIT 1を試しましたか?これは、DELETEクエリに一致する行の1つのみを削除します

DELETE FROM `table_name` WHERE `column_name`='value' LIMIT 1;
4
Feelsbadman

私の場合、関連する最大値を使用できます。

DELETE FROM [table] where id in 
(select max(id) from [table] group by id, col2, col3 having count(id) > 1)

最初に結果をテストし、「持つ」節に制限条件があることを確認してください。このような巨大な削除クエリでは、最初にデータベースを更新する必要があります。

2
TIm

私の場合、私はcould GUIを取得して、問題の行の値の文字列を取得します(あるいは、これを手作業で行うこともできます)。借金が残っている同僚の提案で、私はこれを使用してINSERTステートメントを作成しました。

INSERT
'ID1219243408800307444663', '2004-01-20 10:20:55', 'INFORMATION', 'admin' (...)
INTO some_table;

Insertステートメントをテストしたので、3つ組になりました。最後に、単純なDELETEを実行してすべてを削除しました...

DELETE FROM some_table WHERE logid = 'ID1219243408800307444663';

その後、もう一度INSERTを実行すると、1行になり、主キーの明るい可能性が残ります。

1
david.libremone

次のような列を追加できる場合

  ALTER TABLE yourtable ADD IDCOLUMN bigint NOT NULL IDENTITY (1, 1)

そうする。

次に、カウント> 1の問題のある列でグループ化された行をカウントします。これにより、双子(または三重線など)が識別されます。

次に、コンテンツが上記の特定されたコンテンツと等しい問題の列を選択し、IDCOLUMNのIDを確認します。

iDCOLUMNがそれらのIDの1つに等しいテーブルから削除します。

1
Der U

これはPostgreSQLで機能します

DELETE FROM tablename WHERE id = 123 AND ctid IN (SELECT ctid FROM tablename WHERE id = 123 LIMIT 1)
1
Vlad B

PostgreSQLには、ctidと呼ばれる暗黙の列があります。 wiki を参照してください。したがって、以下を自由に使用できます。

WITH cte1 as(
    SELECT unique_column, max( ctid ) as max_ctid
    FROM table_1
    GROUP BY unique_column
    HAVING count(*) > 1
), cte2 as(
    SELECT t.ctid as target_ctid
    FROM table_1 t
    JOIN cte1 USING( unique_column )
    WHERE t.ctid != max_ctid
)
DELETE FROM table_1
WHERE ctid IN( SELECT target_ctid FROM cte2 )

同時更新の可能性がある場合にこれを使用することがどれほど安全かはわかりません。そのため、LOCK TABLE table_1 IN ACCESS EXCLUSIVE MODE;実際にクリーンアップを行う前。

0
volvpavl

テーブルにGuid列を追加し、各行の新しいIDを生成するように設定しました。その後、GUIを使用して行を削除できます。

0
Ian Warburton

削除する複数の重複行があり、すべてのフィールドが同一で、異なるIDがなく、テーブルに主キーがない場合、1つのオプションは、重複しない行を新しいテーブルに保存して、重複するすべての行を削除し、行を挿入することです。これは、テーブルが本当に大きく、重複行の数が少ない場合に役立ちます。

---  col1 , col2 ... coln are the table columns that are relevant. 
--- if not sure add all columns of the table in the select bellow and the where clause later. 

--- make a copy of the table T to be sure you can rollback anytime , if possible
--- check the @@rowcount to be sure it's what you want
--- use transactions and rollback in case there is an error 

--- first find all with duplicate rows that are identical , this statement could be joined 
--- with the first one if you choose all columns 

select col1,col2, --- other columns as needed
  count(*) c into temp_duplicate group by col1,col2 having count(*) > 1 

--- save all the rows that are identical only once ( DISTINCT ) 

insert distinct * into temp_insert from T , temp_duplicate D where
T.col1 = D.col1 and
T.col2 = D.col2 --- and other columns if needed

--- delete all the rows that are duplicate

delete T from T , temp_duplicate D where 
T.col1 = D.col1 and
T.col2 = D.col2 ---- and other columns if needed

--- add the duplicate rows , now only once
insert into T select * from temp_insert 

--- drop the temp tables after you check all is ok 
0
detzu