2016-10-08 5 views
3

나는 테이블에서 중복을 제거하기 위해 postgres 쿼리 작업을하고있다. 다음 표는 동적으로 생성되며 첫 번째 행에 중복 값이있는 경우 레코드를 제거 할 선택 쿼리를 작성하려고합니다.PostgreSQL 중복 제거

표는 내가 제거 선택 쿼리를 작성하려면이

Ist col 2nd col 
4  62 
6  34 
5  26 
5  12 

같이 보입니다 중 3 행 또는 행 중 하나를 유지하려는 경우 4.

+1

당신은 의미합니까? –

+0

@ Hack-R 수를 계산할 수는 있지만 어떻게 행을 제거 할 수 있습니까 ?? 죄송합니다. 바보 같은 질문 인 경우 – Uasthana

+0

체크 아웃 http://stackoverflow.com/questions/26769454/how-to-delete-duplicate-rows-in-postgresql –

답변

1

@ 당신의 도움에 대한 중간 테이블에 대한 필요가 없습니다.당신은 단지 하나 개의 컬럼에 대해 고유 한 값을 얻고 싶다면


, 당신은 사용할 수 있습니다

select distinct on (first_column) * 
from the_table 
order by the_table; 

또는 단순히

select first_column, min(second_column) 
from the_table 
group by first_column; 
+0

우리는 삭제하기를 원하지 않습니다. 유일한 행을 선택하십시오. – Uasthana

+0

@Uththana : 흠, 테이블에서 중복을 제거하는 방법 * ". –

+1

그러면 행 1과 2와 4가 삭제 될 것입니다 ... 나는 그가 단지 4 번 행을 삭제하려고한다고 생각합니다. –

2
   select count(first) as cnt, first, second 
      from df1 
      group by first 
      having(count(first) = 1) 

(죄송합니다

   select first, min(second) 
      from df1 
      group by first 

테이블의 이름이인 경우 : 내가 처음 당신이) 것을 원한다면 그것을 놓쳤다이고 열의 이름은 firstsecond입니다.

원하는 경우 실제로는 count(first) as cnt을 생략 할 수 있습니다.

분명히 알 수있는 위험이 있으므로 원하는 데이터를 선택하는 방법을 알았 으면 12 가지 방법 중 하나를 레코드를 삭제하는 것이 간단합니다.

당신은 테이블을 교체하거나 그냥 삭제 create table as를 사용할 수있는 새로운 테이블을 확인하려면 :

   create table tmp as 
      select count(first) as cnt, first, second 
      from df1 
      group by first 
      having(count(first) = 1); 

      drop table df1; 

      create table df1 as select * from tmp; 

또는 DELETE FROM를 사용하여 :

DELETE FROM df1 WHERE first NOT IN (SELECT first FROM tmp); 

또한 select into를 사용하는 등 수를 등

+0

@ cricket_007 ?? –

+0

위의 "행을 어떻게 제거 할 수 있습니까?"를 참조하십시오. 또한 질문에서 "중복 테이블을 제거하십시오" –

+0

@ Hack-R이 작동하지 않았다, 쿼리가 두 행을 모두 지 웠습니다 – Uasthana

0

기본적으로 나는 이것을했다

create temp t1 as 
select first, min (second) as second 
from df1 
group by first 

select * from df1 
inner join t1 on t1.first = df1.first and t1.second = df1.second 

만족스러운 답변입니다.

delete from df1 
where ctid not in (select min(ctid) 
        from df1 
        group by first_column 
        having count(*) > 1); 

가 큰 테이블에서 많은 행을 삭제하는 경우는, 중간 테이블 접근 방식은 아마도 빠른 : 감사는 해킹-R

1
  • 당신이 SELECT 고유 행을 원하는 경우 :

SELECT * FROM ztable nu 
WHERE EXISTS (   -- another record exists 
    SELECT * FROM ztable x 
    WHERE x.id = nu.id -- with the same id 
    AND x.ctid < nu.ctid -- , but with a different(lower) "internal" rowid 
    ); 

  • 당신이 원하는 경우에 :
    • 이전 쿼리에서 억제 된 다른 행을 SELECT하려면
      SELECT * FROM ztable u 
      WHERE NOT EXISTS (  -- There is no other record 
          SELECT * FROM ztable x 
          WHERE x.id = u.id -- with the same id 
          AND x.ctid < u.ctid -- , but with a different(lower) "internal" rowid 
          );     -- so u.* must be unique 
      
      DELETE 개 기록, 테이블이 고유하게 (그러나 ID 당 하나 개의 기록을 유지) : 최초의 열은 중복이있는 경우

    DELETE FROM ztable d 
    WHERE EXISTS (   -- another record exists 
        SELECT * FROM ztable x 
        WHERE x.id = d.id -- with the same id 
        AND x.ctid < d.ctid -- , but with a different(lower) "internal" rowid 
        ); 
    
+0

호기심에서 벗어나 더 많은 조건을 기반으로 행을 보존 할 필요가 있고 무작위를 삭제하는 것이 아니라면 (ctid가 수행하고 있다고 생각하는) 'ctid'로 접근하면 안됩니다. 맞습니까? 나는 그것이 장기적으로 안정적이지 않다는 것을 의미한다. –

+1

ctid는 삭제 또는 선택을위한 다양한 후보를 구별하기 위해 다른 열을 사용할 수없는 경우 마지막 수단으로 사용됩니다. (다른 DBMS에는 다른 이름을 가진 비슷한 의사 컬럼이 있습니다.)이 특별한 경우에 'second_col'이 사용되었을 수 있습니다. 가장 낮은 (또는 가장 높은) 컬럼 만 유지할 수있었습니다. – wildplasser

+0

@wildplasser 어느 해결책도 작동하지 않습니다 ... – Uasthana