417

次のフィールドを持つテーブルがあります。

id (Unique)
url (Unique)
title
company
site_id

ここで、同じ行を削除する必要がありますtitle, company and site_idPHPこれを行う 1 つの方法は、スクリプト ( )と共に次の SQL を使用することです。

SELECT title, site_id, location, id, count( * ) 
FROM jobs
GROUP BY site_id, company, title, location
HAVING count( * ) >1

このクエリを実行した後、サーバー サイド スクリプトを使用して重複を削除できます。

しかし、これが SQL クエリを使用してのみ実行できるかどうかを知りたいです。

4

26 に答える 26

643

これを行うための本当に簡単な方法はUNIQUE、3つの列にインデックスを追加することです。ALTERステートメントを書くときは、IGNOREキーワードを含めてください。そのようです:

ALTER IGNORE TABLE jobs
ADD UNIQUE INDEX idx_name (site_id, title, company);

これにより、重複するすべての行が削除されます。追加の利点として、INSERTs重複する将来はエラーになります。いつものように、このようなものを実行する前にバックアップを取ることをお勧めします...

于 2010-07-22T18:24:05.253 に答える
208

列のプロパティを変更したくない場合は、以下のクエリを使用できます。

一意の ID (列など) を持つ列があるauto_incrementため、それを使用して重複を削除できます。

DELETE `a`
FROM
    `jobs` AS `a`,
    `jobs` AS `b`
WHERE
    -- IMPORTANT: Ensures one version remains
    -- Change "ID" to your unique column's name
    `a`.`ID` < `b`.`ID`

    -- Any duplicates you want to check for
    AND (`a`.`title` = `b`.`title` OR `a`.`title` IS NULL AND `b`.`title` IS NULL)
    AND (`a`.`company` = `b`.`company` OR `a`.`company` IS NULL AND `b`.`company` IS NULL)
    AND (`a`.`site_id` = `b`.`site_id` OR `a`.`site_id` IS NULL AND `b`.`site_id` IS NULL);

MySQL では、 NULL セーフの等号演算子(別名「宇宙船演算子」 )を使用して、さらに単純化できます。

DELETE `a`
FROM
    `jobs` AS `a`,
    `jobs` AS `b`
WHERE
    -- IMPORTANT: Ensures one version remains
    -- Change "ID" to your unique column's name
    `a`.`ID` < `b`.`ID`

    -- Any duplicates you want to check for
    AND `a`.`title` <=> `b`.`title`
    AND `a`.`company` <=> `b`.`company`
    AND `a`.`site_id` <=> `b`.`site_id`;
于 2014-08-08T15:20:38.567 に答える
80

MySQL には、削除元のテーブルの参照に関する制限があります。次のような一時テーブルを使用して、これを回避できます。

create temporary table tmpTable (id int);

insert  into tmpTable
        (id)
select  id
from    YourTable yt
where   exists
        (
        select  *
        from    YourTabe yt2
        where   yt2.title = yt.title
                and yt2.company = yt.company
                and yt2.site_id = yt.site_id
                and yt2.id > yt.id
        );

delete  
from    YourTable
where   ID in (select id from tmpTable);

コメントでの Kostanos の提案から:
上記の唯一の遅いクエリは、非常に大きなデータベースがある場合の DELETE です。このクエリはより高速になる可能性があります。

DELETE FROM YourTable USING YourTable, tmpTable WHERE YourTable.id=tmpTable.id
于 2010-07-22T18:26:48.977 に答える
48

私の場合のIGNOREようにステートメントが機能しない場合は、次のステートメントを使用できます。

CREATE TABLE your_table_deduped LIKE your_table;


INSERT your_table_deduped
SELECT *
FROM your_table
GROUP BY index1_id,
         index2_id;

RENAME TABLE your_table TO your_table_with_dupes;

RENAME TABLE your_table_deduped TO your_table;

#OPTIONAL
ALTER TABLE `your_table` ADD UNIQUE `unique_index` (`index1_id`, `index2_id`);

#OPTIONAL
DROP TABLE your_table_with_dupes;
于 2013-01-31T10:10:53.573 に答える
33

別の解決策があります:

DELETE t1 FROM my_table t1, my_table t2 WHERE t1.id < t2.id AND t1.my_field = t2.my_field AND t1.my_field_2 = t2.my_field_2 AND ...
于 2015-02-01T18:17:00.473 に答える
10

これにより、タイトル、会社、サイトの値が同じ重複行が削除されます。最初に出現したものが保持され、残りの重複はすべて削除されます

DELETE t1 FROM tablename t1
INNER JOIN tablename t2 
WHERE 
    t1.id < t2.id AND
    t1.title = t2.title AND
    t1.company=t2.company AND
    t1.site_ID=t2.site_ID;
于 2019-11-21T19:19:56.343 に答える
7

私はSQLServer用のこのクエリスニペットを持っていますが、ほとんど変更を加えることなく他のDBMSで使用できると思います。

DELETE
FROM Table
WHERE Table.idTable IN  (  
    SELECT MAX(idTable)
    FROM idTable
    GROUP BY field1, field2, field3
    HAVING COUNT(*) > 1)

このクエリでは、重複した行のIDが最も小さい行は削除されないことをお伝えするのを忘れました。これがうまくいく場合は、次のクエリを試してください。

DELETE
FROM jobs
WHERE jobs.id IN  (  
    SELECT MAX(id)
    FROM jobs
    GROUP BY site_id, company, title, location
    HAVING COUNT(*) > 1)
于 2010-07-22T18:22:08.597 に答える
5

すべてのケースでシンプルかつ高速:

CREATE TEMPORARY TABLE IF NOT EXISTS _temp_duplicates AS (SELECT dub.id FROM table_with_duplications dub GROUP BY dub.field_must_be_uniq_1, dub.field_must_be_uniq_2 HAVING COUNT(*)  > 1);

DELETE FROM table_with_duplications WHERE id IN (SELECT id FROM _temp_duplicates);
于 2016-12-09T10:56:54.160 に答える
-2

どのレコードを削除するかをもう少し具体的にしたいので、私の解決策は次のとおりです。

delete
from jobs c1
where not c1.location = 'Paris'
and  c1.site_id > 64218
and exists 
(  
select * from jobs c2 
where c2.site_id = c1.site_id
and   c2.company = c1.company
and   c2.location = c1.location
and   c2.title = c1.title
and   c2.site_id > 63412
and   c2.site_id < 64219
)
于 2013-05-21T20:51:56.803 に答える