andを持つテーブルbusiness_users
があり、重複があります。1 つを除いてすべての重複を削除するクエリを作成するにはどうすればよいですか?user_id
business_id
2 に答える
完全に同一の行
最初にあなたの質問を理解したように、完全に同一の行を避けたい場合は、別のテーブルに一意の行を選択し、そこからテーブル データを再作成できます。
CREATE TEMPORARY TABLE tmp SELECT DISTINCT * FROM business_users;
DELETE FROM business_users;
INSERT INTO business_users SELECT * FROM tmp;
DROP TABLE tmp;
ただし、このテーブルを参照する外部キー制約がある場合は注意してください。行を一時的に削除すると、他の場所でカスケード削除が発生する可能性があります。
ユニーク制約の導入
user_id
とのペアのみを気にする場合はbusiness_id
、おそらく将来重複することを避けたいと思うでしょう。既存のデータを一時テーブルに移動し、制約を追加してから、重複を無視してテーブル データを元に戻すことができます。
CREATE TEMPORARY TABLE tmp SELECT * FROM business_users;
DELETE FROM business_users;
ALTER TABLE business_users ADD UNIQUE (user_id, business_id);
INSERT IGNORE INTO business_users SELECT * FROM tmp;
DROP TABLE tmp;
上記の回答は、この回答に基づいています。外部キーに関する警告は、上記のセクションと同様に適用されます。
ワンショット除去
テーブル構造をまったく変更せずに単一のクエリのみを実行し、id
各行を識別する主キーがある場合は、次のことを試すことができます。
DELETE FROM business_users WHERE id NOT IN
(SELECT MIN(id) FROM business_users GROUP BY user_id, business_id);
同様のアイデアが以前にこの回答で提案されていました。
上記のリクエストが失敗した場合、同じステップでテーブルの読み取りと削除が許可されていないため、一時テーブルを再度使用できます。
CREATE TEMPORARY TABLE tmp
SELECT MIN(id) id FROM business_users GROUP BY user_id, business_id;
DELETE FROM business_users WHERE id NOT IN (SELECT id FROM tmp);
DROP TABLE tmp;
必要に応じて、この方法でデータを消去した後でも、一意性制約を導入できます。これを行うにはALTER TABLE
、前のセクションの行を実行します。
主キーがあるので、それを使用して、保持する行を選択できます。
delete from business_users
where id not in (
select id from (
select min(id) as id -- Make a list of the primary keys to keep
from business_users
group by user_id, business_id -- Group by your duplicated row definition
) as a -- Derived table to force an implicit temp table
);
このようにして、一時テーブルなどを作成/削除する必要はありません(暗黙的なテーブルを除く)。
user_id, business_id
これについて再度心配する必要がないように、一意の制約を設定することをお勧めします。