2016-06-27 2 views
0

어떤 이유로 인해 카테고리 ID를 PK하지 않고 "카테고리"테이블을 만든 시스템에서 작업하고 있습니다. 이제 테이블에 모든 행이 중복되어 일부 쿼리에 문제가 있음을 알았습니다.PK없는 테이블에서 삭제 된 행의 개수 제한

내 질문은 : 색인에 의존하지 않고 테이블에 '원본'을 남겨두고 중복 행을 삭제하는 방법이 있습니까?

다음은 SELECT * FROM categories의 : 테이블에 정의 된 인덱스가

+-----------+-------------+ 
| categoria | descripcion | 
+-----------+-------------+ 
|   1 | Int.Cons. | 
|   2 | Delegado | 
|   3 | Personal | 
|   4 | Comun  | 
|   5 | Proveedor | 
|   6 | Menor/Inc | 
|  11 | N/Categoria | 
|   1 | Int.Cons. | 
|   2 | Delegado | 
|   3 | Personal | 
|   4 | Comun  | 
|   5 | Proveedor | 
|   6 | Menor/Inc | 
|  11 | N/Categoria | 
+-----------+-------------+ 

없습니다.

CREATE TABLE xyz AS SELECT DISTINCT FROM categories; 
DROP TABLE categories; 
ALTER TABLE xyz RENAME categories; 
CREATE UNIQUE INDEX idx_nn_c_1 ON categories(id); 

답변

1

몇 가지 방법으로 레코드를 삭제할 수 있습니다. 아마-다시 채우기 올바르게 테이블을 다음 임시 테이블을 사용하는 것이 좋습니다과 같습니다

create temporary table temp_categories as 
    select c.id, c.descripcion 
    from categories c 
    group by c.id; 

truncate table categories; 

insert into categories(id, descripcion) 
    select id, descripcion 
    from temp_categories; 


alter table add constraint primary key (id); 
alter table add constraint unq_categories_descripcion unique (descripcion); 
+0

입니다. 임시 테이블 (CREATE TEMPORARY TABLE temp_categories)을 만들어야한다는 점을 추가하고 싶습니다. 권한이 부족하기 때문에 모든 것이 작동합니다. 감사! – Sebastianb

0

당신은 당신이 아주 쉽게이 작업을 수행 할 수 있습니다 준
+0

이 작업은 가능하지만 db에 CREATE TABLE 권한이 없습니다. 여하튼 임시 테이블과 함께 사용할 수 있습니까? – Sebastianb

+0

플랫 파일에서 데이터를 대체 덤프하고 카테고리 테이블을 자르고 데이터를 다시로드 할 수 있습니다. –

0

시험이

delete a from yourtable a1 , yourtable a2 where a1.categoria=a2.categoria 
(당신이 DROP 라인에서 테이블을 잃어 버리게된다 다른 실행하기 전에 SQL을 확인) :이 예에서
+0

MySQL이 WITH 절을 지원하지 않는다고 생각합니다. https://bugs.mysql.com/bug.php?id=16244 – Sebastianb

+0

죄송합니다. MSSQL에 대한 생각은 – satsvelke

1

새 테이블을 생성하는 옵션이 아니므로,이 같은 뭔가를 실행할 수 있습니다/IF; 그러나 모든 중복이 사라질 때까지 반복해서 실행해야합니다.

DELETE FROM categories 
WHERE (categoria, descripcion) IN (
    SELECT categoria, descripcion 
    FROM categories 
    GROUP BY categoria, descripcion 
    HAVING COUNT(*) > 1 
) 
LIMIT 1 
; 

편집 : 실제로,이 위험하지 않고 임시 테이블 솔루션의 혜택을해야한다 (진정한 임시 테이블을 연결하면 데이터를 잃게 실패하면 세션/연결을 기반으로하기 때문에) .

INSERT INTO categories (categoria, descripcion) 
SELECT DISTINCT categoria, CONCAT('NEWCOPY---', descripcion) 
FROM categories 
; 

DELETE FROM categories 
WHERE descripcion NOT LIKE 'NEWCOPY---%' 
; 

UPDATE categories 
SET descripcion = REPLACE(descripcion, 'NEWCOPY---', '') 
; 

물론, 'newcopy를이 ---'/ 당신이 테이블에 존재하지 알고 접두사로 대체해야 할 수 있습니다.

+0

나는 temp_table 솔루션을 따라 갔다.하지만 누군가가 임시 테이블에 대한 권한을 너무 갖고 있지 않다면 이것은 좋은 대안이 될 수있다. – Sebastianb

+0

@Sebastianb는 다른 대안 (임시 테이블보다 안전합니다)에 대한 편집을 참조하십시오. – Uueerdo