2012-09-18 2 views
3

테이블 business_usersuser_idbusiness_id이며 사본이 있습니다. 중복을 제외한 모든 중복을 삭제하는 쿼리를 작성하려면 어떻게해야합니까?하나만 제외하고 모든 복제본 삭제

+1

관련 질문을 클릭하십시오. 나는이 문제를 찾고있을 때 몇 주 전에 여러 가지 아이디어를 발견했다. 원하는 결과를 얻기 위해 몇 가지를 섞어서 사용했습니다. – MetalFrog

+2

이 테이블에 기본 키나 다른 고유 제한 조건이 있습니까? 아니면 전체 행이 중복되도록'user_id'와'business_id'만이 유일한 컬럼입니까? – ruakh

+0

http://stackoverflow.com/questions/672702/how-to-delete-duplicates-in-mysql-table의 복제본처럼 보이십니까?rq = 1 – cptScarlet

답변

9

완전히 동일한 행

당신은 내가 처음에, 당신은 별도의 테이블에 고유 행을 선택하고 해당에서 테이블 데이터를 다시 만들 수 있습니다 귀하의 질문을 이해로서, 완전히 동일한 행을 피하려면

. 하지만,이 테이블을 참조하는 모든 외래 키 제약 조건이있는 경우 행의 임시 삭제 다른 곳 계단식 삭제로 이어질 수도로
CREATE TEMPORARY TABLE tmp SELECT DISTINCT * FROM business_users; 
DELETE FROM business_users; 
INSERT INTO business_users SELECT * FROM tmp; 
DROP TABLE tmp; 

은주의해야합니다. 당신은 단지 user_idbusiness_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; 

위의 대답은 this answer을 기반으로합니다. 외래 키에 대한 경고는 위의 섹션 에서처럼 적용됩니다.

원샷 제거

만 어떤 방법으로 테이블 구조를 수정하지 않고, 하나의 쿼리를 실행하려면, 당신은 각 행을 식별하는 기본 키 id있는 경우에, 당신은 다음을 시도 할 수 있습니다 :

비슷한 아이디어가 this answer에 의해 이전에 제안되었습니다. 당신은 아직 할 수있는, 당신이 원하는 경우

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 행을 실행하십시오. 기본 키를 가지고 있기 때문에

+0

마지막으로 좋아하지만 얻을 수 있습니다. FROM 절의 업데이트를 위해 'business_users'대상 테이블을 지정할 수 없습니다. – Trace

+0

@Trace, 피할 수있는 버전을 추가했습니다. 그 문제. – MvG

+0

첫 번째 예제에는 SELECT MIN (id) FROM이 있고 두 번째 예제에는 SELECT MIN (id) id FROM (두 번째 ID에는 두 개의 ID가 있음)이있는 이유는 무엇입니까? – Pete

3

, 유지할 행을 선택하는 것을 사용할 수 있습니다

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 
); 

을 이러한 방법으로, 당신은합니다 (implicit one 제외/드롭 임시 테이블을 만들 필요가 없습니다).

user_id, business_id에 고유 제한을 두어 나중에 다시 염려 할 필요가 없습니다.

+0

멋져 보이지만 이걸 얻을 수 있습니다. FROM 절 – Trace

+0

@Trace에서 업데이트 할 대상 테이블 'business_users'를 지정할 수 없습니다. 죄송합니다 ...이 시나리오에서는 mysql에서 하위 쿼리 작업을 수행하도록 업데이트했습니다. –

+0

참고 : 하위 쿼리 사용에 대한 동일한 제안을 읽었지 만 자체 테스트 설정에서는 실패했습니다. 테스트 용으로'business_users'를 임시 테이블로 만들었 기 때문에 생긴 것 같습니다. 이 경우 오류는 '테이블을 다시 열 수 없습니다 :'business_users '라는 문구가 있습니다 (적어도 내 눈에는 마찬가지 임).하지만 다른 하위 쿼리를 도입하면 피할 수 없습니다. – MvG

관련 문제