복붙노트

[RUBY-ON-RAILS] 어떻게 MySQL의 데이터베이스에 중복 레코드를 삭제하려면?

RUBY-ON-RAILS

어떻게 MySQL의 데이터베이스에 중복 레코드를 삭제하려면?

레일 또는 MySQL의 쿼리를 사용하여 MySQL 데이터베이스에 중복 레코드를 삭제하는 가장 좋은 방법은 무엇입니까?

해결법

  1. ==============================

    1.당신이 할 수있는 일은 새 테이블로로 별개의 기록을 복사 할 수 있습니다 :

    당신이 할 수있는 일은 새 테이블로로 별개의 기록을 복사 할 수 있습니다 :

     select distinct * into NewTable from MyTable
    
  2. ==============================

    2.여기에 특별한 언어의 또 다른 아이디어는 다음과 같습니다

    여기에 특별한 언어의 또 다른 아이디어는 다음과 같습니다

    rs = `select a, b, count(*) as c from entries group by 1, 2 having c > 1`
    rs.each do |a, b, c|
      `delete from entries where a=#{a} and b=#{b} limit #{c - 1}`
    end
    

    편집하다:

    그 "필요"힌트 올라프 했네 :)

  3. ==============================

    3.그것은 작은 테이블이 레일에서, 만약 아니라, 당신이 할 수있는 콘솔

    그것은 작은 테이블이 레일에서, 만약 아니라, 당신이 할 수있는 콘솔

    class ActiveRecord::Base
      def non_id_attributes
        atts = self.attributes
        atts.delete('id')
        atts
      end
    end
    
    duplicate_groups = YourClass.find(:all).group_by { |element| element.non_id_attributes }.select{ |gr| gr.last.size > 1 }
    redundant_elements = duplicate_groups.map { |group| group.last - [group.last.first] }.flatten
    redundant_elements.each(&:destroy)
    
  4. ==============================

    4.

    SELECT DISTINCT(req_field) AS field, COUNT(req_field) AS fieldCount FROM 
    table_name GROUP BY req_field HAVING fieldCount > 1
    

    DELETE FROM table_name 
    USING table_name, table_name AS vtable 
    WHERE 
        (table_name.id > vtable.id) 
    AND (table_name.req_field=req_field)
    

    req_field 및 TABLE_NAME 교체 - 문제없이 작동합니다.

  5. ==============================

    5.SQL에 새로운 :-) 이것은 고전적인 질문입니다 - 종종 인터뷰를 요청 :-) 나는 MYSQL에서 일 것입니다 여부를 알 수없는하지만 대부분의 데이터베이스에서 작동 -

    SQL에 새로운 :-) 이것은 고전적인 질문입니다 - 종종 인터뷰를 요청 :-) 나는 MYSQL에서 일 것입니다 여부를 알 수없는하지만 대부분의 데이터베이스에서 작동 -

    > create table t(
    >     a char(2),
    >     b char(2),
    >     c smallint )
    
    > select a,b,c,count(*) from t
    > group by a,b,c
    > having count(*) > 1
    a  b  c
    -- -- ------ -----------
    (0 rows affected)
    
    > insert into t values ("aa","bb",1)
    (1 row affected)
    
    > insert into t values ("aa","bb",1)
    (1 row affected)
    
    > insert into t values ("aa","bc",1)
    (1 row affected)
    
    > select a,b,c,count(*) from t group by a,b,c having count(*) > 1
    a  b  c 
    -- -- ------ -----------
    aa bb      1           2
    (1 row affected)
    
  6. ==============================

    6.당신은 테이블의 PK (ID) (EMP)가 이름 열이 나이가 삭제 중복 레코드로합니다. 대용량 데이터에 대한 쿼리를 수행하는 것은 좋은 방법이 될 수 있습니다.

    당신은 테이블의 PK (ID) (EMP)가 이름 열이 나이가 삭제 중복 레코드로합니다. 대용량 데이터에 대한 쿼리를 수행하는 것은 좋은 방법이 될 수 있습니다.

    DELETE t3
    FROM (
            SELECT t1.name, t1.id
            FROM (
                    SELECT name
                    FROM EMP
                    GROUP BY name
                    HAVING COUNT(name) > 1
            ) AS t0 INNER JOIN EMP t1 ON t0.name = t1.name
    ) AS t2 INNER JOIN EMP t3 ON t3.name = t2.name
    WHERE t2.id < t3.id;
    
  7. ==============================

    7.우리는 테이블 이름 tbl_product을 가지고 필드 p_pi_code에 duplicacy이 더 카운트 후 최대에 p_nats_id없는 가정 먼저 기존 테이블의 데이터를 삽입 새 테이블을 만들 ... 즉 tbl_product에서 newtable1에 경우 다른 다음 newtable1 아무것도 newtable2에

    우리는 테이블 이름 tbl_product을 가지고 필드 p_pi_code에 duplicacy이 더 카운트 후 최대에 p_nats_id없는 가정 먼저 기존 테이블의 데이터를 삽입 새 테이블을 만들 ... 즉 tbl_product에서 newtable1에 경우 다른 다음 newtable1 아무것도 newtable2에

    CREATE TABLE `newtable2` (                                  
                `p_id` int(10) unsigned NOT NULL auto_increment,         
                `p_status` varchar(45) NOT NULL,                         
                `p_pi_code` varchar(45) NOT NULL,                        
                `p_nats_id` mediumint(8) unsigned NOT NULL,              
                `p_is_special` tinyint(4) NOT NULL,                      
                 PRIMARY KEY (`p_id`)                                   
          ) ENGINE=InnoDB;
    
    INSERT INTO newtable1 (p_status, p_pi_code, p_nats_id, p_is_special) SELECT 
        p_status, p_pi_code, p_nats_id, p_is_special FROM tbl_product group by p_pi_code;
    
    INSERT INTO newtable2 (p_status, p_pi_code, p_nats_id, p_is_special) SELECT 
        p_status, p_pi_code, p_nats_id, p_is_special FROM newtable1 group by p_nats_id;
    

    우리가 보는 것을 경기장에있는 모든 duplicacy가 제거됩니다

  8. ==============================

    8.나는 오라클에 최근에이 작업을 수행 할 수 있었지만 단계는 MySQL의에서 동일한했을 것이다. 그것은 내 프로세스가 중복 제거를 할 수 있도록 비교적 헤비급이었다 내가 작업에 사용하고있는 무슨에 비해 적어도 많은 데이터를했다. 나는 다른 사람이 비슷한 문제와 함께 제공 여기 경우를 포함하고있다.

    나는 오라클에 최근에이 작업을 수행 할 수 있었지만 단계는 MySQL의에서 동일한했을 것이다. 그것은 내 프로세스가 중복 제거를 할 수 있도록 비교적 헤비급이었다 내가 작업에 사용하고있는 무슨에 비해 적어도 많은 데이터를했다. 나는 다른 사람이 비슷한 문제와 함께 제공 여기 경우를 포함하고있다.

    내 중복 레코드는 서로 다른 ID를 다른 updated_at 시간, 가능한 ID를 updated_by 다른, 다른 모든 열이 동일했다. 나는 가장 최근에 중복 설정의 업데이트를 유지하고 싶었다.

    나는 레일 로직과 SQL이 그것을 끝낼 수의 조합을 사용했다.

    단계 하나 : 모델 로직을 사용하여 중복 레코드의 ID를 식별하는 레이크 스크립트를 실행합니다. ID는 텍스트 파일로 이동합니다.

    두 번째 단계는 다음 ID가 텍스트 파일에서로드, 삭제, 한 열이있는 임시 테이블을 만들 수 있습니다.

    3 단계 : I 삭제거야 모든 레코드와 다른 임시 테이블 생성 (경우에 대비를!).

    CREATE TABLE temp_duplicate_models 
      AS (SELECT * FROM models 
      WHERE id IN (SELECT * FROM temp_duplicate_ids));
    

    4 단계 : 실제 삭제.

    DELETE FROM models WHERE id IN (SELECT * FROM temp_duplicate_ids);
    
  9. ==============================

    9.당신이 사용할 수있는:

    당신이 사용할 수있는:

    http://lenniedevilliers.blogspot.com/2008/10/weekly-code-find-duplicates-in-sql.html

    중복을 얻을 후 바로 루비 코드 또는 SQL 코드를 통해 삭제하기 (I는 SQL 코드에서 그것을 할 수 있지만 최대 이잖아 것입니다 :-)

  10. ==============================

    10.테이블에 PK를 가지고 (또는 당신이 쉽게 그것을 하나를 줄 수있는) 경우에, 당신은 조금 지저분한보고 될 수있다 (다음 쿼리 (자격에 중복 같다)와 동일하게 테이블의 컬럼의 수를 지정할 수 있지만, 수 공장):

    테이블에 PK를 가지고 (또는 당신이 쉽게 그것을 하나를 줄 수있는) 경우에, 당신은 조금 지저분한보고 될 수있다 (다음 쿼리 (자격에 중복 같다)와 동일하게 테이블의 컬럼의 수를 지정할 수 있지만, 수 공장):

    DELETE FROM table WHERE pk_id IN(
       SELECT DISTINCT t3.pk_id FROM (
           SELECT t1.* FROM table AS t1 INNER JOIN (
               SELECT col1, col2, col3, col4, COUNT(*) FROM table
               GROUP BY col1, col2, col3, col4 HAVING COUNT(*)>1) AS t2
           ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3 AND
           t1.col4 = t2.col4)
       AS t3, (
           SELECT t1.* FROM table AS t1 INNER JOIN (
               SELECT col1, col2, col3, col4, COUNT(*) FROM table
               GROUP BY col1, col2, col3, col4 HAVING COUNT(*)>1) AS t2
           ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3 AND
           t1.col4 = t2.col4)
       AS t4
       WHERE t3.col1 = t4.col1 AND t3.pk_id > t4.pk_id
    

    )

    이는 '새로운'중복 삭제, 데이터베이스에 입력 최초의 기록을 남겨 둘 것이다. 마지막 기록을 유지하려면>에 <전환합니다.

  11. ==============================

    11.MySQL은 내가 좋아하는 뭔가를 넣을 때

    MySQL은 내가 좋아하는 뭔가를 넣을 때

    delete from A where IDA in (select IDA from A )
    

    MySQL은 같은 것을 "당신이 삭제 작업의 선택 부분에서 동일한 테이블을 사용할 수 없습니다"고 말했다.

    난 그냥 몇 가지 중복 레코드를 삭제해야했습니다, 나는 그런 .PHP 프로그램으로 성공

    <?php
    ...
    $res = hacer_sql("SELECT MIN(IDESTUDIANTE) as IDTODELETE 
    FROM `estudiante` group by `LASTNAME`,`FIRSTNAME`,`CI`,`PHONE`
    HAVING COUNT(*) > 1 )");
    while ( $reg = mysql_fetch_assoc($res) ) {
       hacer_sql("delete from estudiante where IDESTUDIANTE = {$reg['IDTODELETE']}");
    }
    ?>
    
  12. ==============================

    12.나는 테이블 변경을 사용하고 있습니다

    나는 테이블 변경을 사용하고 있습니다

    ALTER IGNORE TABLE jos_city ADD UNIQUE INDEX(`city`);
    
  13. ==============================

    13.나는 약 70,000 항목과 테이블에 다음과 같은 작업을 수행 할 위 @ krukid의 답변을 사용 :

    나는 약 70,000 항목과 테이블에 다음과 같은 작업을 수행 할 위 @ krukid의 답변을 사용 :

    rs = 'select a, b, count(*) as c from table group by 1, 2 having c > 1'
    
    # get a hashmap
    dups = MyModel.connection.select_all(rs)
    
    # convert to array
    dupsarr = dups.map { |i|  [i.a, i.b, i.c] }
    
    # delete dups
    dupsarr.each do |a,b,c|
        ActiveRecord::Base.connection.execute("delete from table_name where a=#{MyModel.sanitize(a)} and b=#{MyModel.sanitize(b)} limit #{c-1}")
    end
    
  14. ==============================

    14.여기에 내가 생각 해낸 레일 솔루션입니다. 그 한 시간 이동하면 가장 효율적인 있지만 큰 문제가되지 않을 수 있습니다.

    여기에 내가 생각 해낸 레일 솔루션입니다. 그 한 시간 이동하면 가장 효율적인 있지만 큰 문제가되지 않을 수 있습니다.

    distinct_records = MyTable.all.group(:distinct_column_1, :distinct_column_2).map {|mt| mt.id}
    duplicates = MyTable.all.to_a.reject!{|mt| distinct_records.include? mt.id}
    duplicates.each(&:destroy)
    

    첫째, 고유성 결정 모든 컬럼에 의해 그룹은, 예 쇼 2하지만 당신은 더 많거나 적게 가질 수

    둘째, 그 그룹의 역 ... 다른 레코드를 선택

    셋째, 삭제 모든 기록.

  15. ==============================

    15.첫째로 당신은 duplicate.But I를 삭제하고자하는 열을 기준으로 그룹을 그룹의 by.I 자체 조인을 쓰고 함께 그 일을하고 있지 않다.

    첫째로 당신은 duplicate.But I를 삭제하고자하는 열을 기준으로 그룹을 그룹의 by.I 자체 조인을 쓰고 함께 그 일을하고 있지 않다.

    당신은 임시 테이블을 만들 필요가 없습니다.

    하나 개의 레코드를 제외하고 중복 삭제 : 이 표에서는 자동 증가 열이 있어야합니다. 난 그냥 건너했다고 가능한 솔루션 :

    DELETE n1 FROM names n1, names n2 WHERE n1.id > n2.id AND n1.name = n2.name
    

    당신이 가장 낮은 자동 증가 id 값을 가진 행을 유지하려는 경우 또는

    DELETE n1 FROM names n1, names n2 WHERE n1.id < n2.id AND n1.name = n2.name
    

    당신은 가장 높은 자동 증가 id 값을 가진 행을 유지하려는 경우.

    당신은 당신의 솔루션을 확인 교차 다시 중복 찾을 수 있습니다 :

    SELECT * FROM `names` GROUP BY name, id having count(name) > 1;
    

    이 0 결과를 반환하는 경우, 다음 쿼리는 성공적이다.

  16. from https://stackoverflow.com/questions/659906/how-to-delete-duplicate-records-in-mysql-database by cc-by-sa and MIT license