web-dev-qa-db-ja.com

MySQLで重複するレコードを探す

MySQLデータベースから重複したレコードを取り出したいです。これは次のようにして行うことができます。

SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1

結果は次のとおりです。

100 MAIN ST    2

重複している各行が表示されるようにプルします。何かのようなもの:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

これがどのように行われることができるかについての任意の考え?私は最初の1つをやることを避けて、コード内の2番目のクエリで重複を調べます。

612
Chris Bartow

重要なのは、このクエリをサブクエリとして使用できるように書き直すことです。

SELECT firstname, 
   lastname, 
   list.address 
FROM list
   INNER JOIN (SELECT address
               FROM   list
               GROUP  BY address
               HAVING COUNT(id) > 1) dup
           ON list.address = dup.address;
649
Powerlord
SELECT date FROM logs group by date having count(*) >= 2
337
trt

なぜINNERだけでテーブルを結合するのではないのでしょうか。

SELECT a.firstname, a.lastname, a.address
FROM list a
INNER JOIN list b ON a.address = b.address
WHERE a.id <> b.id

アドレスが2回以上存在する可能性がある場合は、DISTINCTが必要です。

193
rudolfson

私はこの質問に選ばれた最善の答えを試しましたが、それは私を多少混乱させました。私は実際には自分のテーブルの1つのフィールドでそれを必要としていました。 このリンク からの次の例は、私にとって非常にうまく機能しました。

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;
52
Arman Malik
select `cityname` from `codcities` group by `cityname` having count(*)>=2

これはあなたが求めていたのと同じようなクエリであり、その200%は機能的で簡単です。楽しい!!!

42
pratswinz

電子メールアドレス でこのクエリを使用して重複するユーザを検索してください...

SELECT users.name, users.uid, users.mail, from_unixtime(created)
FROM users
INNER JOIN (
  SELECT mail
  FROM users
  GROUP BY mail
  HAVING count(mail) > 1
) dupes ON users.mail = dupes.mail
ORDER BY users.mail;
35
doublejosh

これは簡単ではありません。

SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1

21
Tudor

重複は1つ以上のフィールドにも依存していることがわかりました。

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;
19

別の解決策は、以下のようにテーブルエイリアスを使うことです。

SELECT p1.id, p2.id, p1.address
FROM list AS p1, list AS p2
WHERE p1.address = p2.address
AND p1.id != p2.id

この場合、本当に元の list テーブルを使って、2つの p retendテーブルを作成するだけです - p 1 p 2 - そのうち、アドレス列で結合を実行します(3行目)。 4行目では、同じレコードが一連の結果に重複して表示されないようにしています(「重複した重複」)。

13
jerdiggity

特に正確さが必要な場合は、重複した addresses を見つけることは予想以上に複雑です。この場合、MySQLクエリでは不十分です...

私は SmartyStreets で仕事をしています。ここでは検証や重複排除などの問題に対処していますが、同様の問題を抱えたさまざまな課題がたくさんあります。

あなたのためにリストに重複を報告するいくつかのサードパーティ製のサービスがあります。 MySQLサブクエリだけでこれを行っても、アドレスフォーマットと標準の違いは説明できません。 USPS(米国住所用)には、これらの標準を作成するための特定のガイドラインがありますが、そのような操作を実行することが認定されているのは、ほんの一握りのベンダーのみです。

だから、私はあなたのための最善の答えは、例えば、CSVファイルにテーブルをエクスポートし、それを有能なリストプロセッサに提出することです。そのようなものが LiveAddress です。これは、数秒から数分で自動的に行われます。それは "Duplicate"と呼ばれる新しいフィールドとその中のYの値で重複行にフラグを立てます。

11
Matt

これにより、1回のテーブルパスで重複が選択され、サブクエリは選択されません。

SELECT  *
FROM    (
        SELECT  ao.*, (@r := @r + 1) AS rn
        FROM    (
                SELECT  @_address := 'N'
                ) vars,
                (
                SELECT  *
                FROM
                        list a
                ORDER BY
                        address, id
                ) ao
        WHERE   CASE WHEN @_address <> address THEN @r := 0 ELSE 0 END IS NOT NULL
                AND (@_address := address ) IS NOT NULL
        ) aoo
WHERE   rn > 1

このクエリはOracleSQL Serverに存在するROW_NUMBER()を実際にエミュレートします。

詳細は私のブログの記事を見てください。

10
Quassnoi

非常に効率的にはなりませんが、うまくいくはずです。

SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;
9
Chad Birch

これはまた、重複がいくつあるかを示し、結合せずに結果を並べ替えます。

SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages` 
GROUP BY  `Language` 
HAVING how_many >=2
ORDER BY how_many DESC
7
Martin Tonev

個人的にこの問い合わせは私の問題を解決しました:

SELECT `SUB_ID`, COUNT(SRV_KW_ID) as subscriptions FROM `SUB_SUBSCR` group by SUB_ID, SRV_KW_ID HAVING subscriptions > 1;

このスクリプトが行うことは、テーブルに複数回存在するすべての加入者IDと見つかった重複の数を表示することです。

これはテーブルの列です:

| SUB_SUBSCR_ID | int(11)     | NO   | PRI | NULL    | auto_increment |
| MSI_ALIAS     | varchar(64) | YES  | UNI | NULL    |                |
| SUB_ID        | int(11)     | NO   | MUL | NULL    |                |    
| SRV_KW_ID     | int(11)     | NO   | MUL | NULL    |                |

それがあなたにとって役立つことを願っています!

4
Ionut Petre

最速重複削除クエリの手順:

/* create temp table with one primary column id */
INSERT INTO temp(id) SELECT MIN(id) FROM list GROUP BY (isbn) HAVING COUNT(*)>1;
DELETE FROM list WHERE id IN (SELECT id FROM temp);
DELETE FROM temp;
4
venkatesh
 SELECT firstname, lastname, address FROM list
 WHERE 
 Address in 
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)
4
Ryan Roper
select * from table_name t1 inner join (select distinct <attribute list> from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

あなたのテーブルのためにそれは何かのようになります

select * from list l1 inner join (select distinct address from list as list2)l2 where l1.address=l2.address

この問い合わせはあなたのリストテーブルの中のすべての異なったアドレスエントリをあなたに与えるでしょう...私があなたが名前の主キーの値などを持っているならこれがどのように働くかわかりません。

4
Neha Patil
SELECT t.*,(select count(*) from city as tt where tt.name=t.name) as count FROM `city` as t where (select count(*) from city as tt where tt.name=t.name) > 1 order by count desc

city をあなたのテーブルと置き換えてください。 name を自分のフィールド名に置き換えます。

3
Lalit Patel
    SELECT *
    FROM (SELECT  address, COUNT(id) AS cnt
    FROM list
    GROUP BY address
    HAVING ( COUNT(id) > 1 ))
2
DJ.
    Find duplicate Records:

    Suppose we have table : Student 
    student_id int
    student_name varchar
    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+

    Now we want to see duplicate records
    Use this query:


   select student_name,student_id ,count(*) c from student group by student_id,student_name having c>1;

+--------------------+------------+---+
| student_name        | student_id | c |
+---------------------+------------+---+
| usman               |        101 | 3 |
| muhammadusmanyaqoob |        103 | 2 |
+---------------------+------------+---+
0
Usman Yaqoob

重複行をすばやく表示するには、単一の単純なクエリを実行できます

ここでは、テーブルをクエリし、同じuser_id、market_place、skuを持つすべての重複行をリストしています。

select user_id, market_place,sku, count(id)as totals from sku_analytics group by user_id, market_place,sku having count(id)>1;

重複した行を削除するには、削除する行を決定する必要があります。たとえば、IDが低い(通常は古い)か、その他の日付情報があります。私の場合、新しいIDは最新の情報なので、低いIDを削除したいだけです。

最初に、適切なレコードが削除されるかどうかを再確認してください。ここで、重複するレコードの中から(一意のIDによって)削除されるレコードを選択しています。

select a.user_id, a.market_place,a.sku from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

次に、削除クエリを実行して、重複を削除します。

delete a from sku_analytics a inner join sku_analytics b where a.id< b.id and a.user_id= b.user_id and a.market_place= b.market_place and a.sku = b.sku;

バックアップ、ダブルチェック、検証、検証バックアップを実行してください。

0
Ganesh Krishnan

Powerlord answer は確かに最善であり、私はもう1つの変更をお勧めします。DBが過負荷にならないようにLIMITを使用します。

SELECT firstname, lastname, list.address FROM list
INNER JOIN (SELECT address FROM list
GROUP BY address HAVING count(id) > 1) dup ON list.address = dup.address
LIMIT 10

WHEREがない場合や結合するときにLIMITを使用するのは良い習慣です。小さい値から始めて、クエリーの重さを確認してから制限を増やしてください。

0
Michał Maluga