[sql] PostgreSQL에서 중복 레코드를 찾는 방법

현재 다음과 같은 중복 필드를 허용하는 “user_links”라는 PostgreSQL 데이터베이스 테이블이 있습니다.

year, user_id, sid, cid

고유 제한 그러나 지금 확인하기 위해 제약 조건을 추가 할 찾고, 현재 “ID”라는 첫 번째 필드 인 year, user_id, sidcid모든 고유하지만 중복 값은 이미이 제약 조건을 위반하는 존재하기 때문에 내가 제약 조건을 적용 할 수 없습니다.

모든 중복 항목을 찾는 방법이 있습니까?



답변

기본 아이디어는 카운트 집계와 함께 중첩 쿼리를 사용하는 것입니다.

select * from yourTable ou
where (select count(*) from yourTable inr
where inr.sid = ou.sid) > 1

내부 쿼리에서 where 절을 조정하여 검색 범위를 좁힐 수 있습니다.


의견에 언급 된 다른 좋은 해결책이 있지만 모든 사람이 읽는 것은 아닙니다.

select Column1, Column2, count(*)
from yourTable
group by Column1, Column2
HAVING count(*) > 1

또는 더 짧게 :

SELECT (yourTable.*)::text, count(*)
FROM yourTable
GROUP BY yourTable.*
HAVING count(*) > 1


답변

PostgreSQL로 중복 행 찾기 “에서 스마트 솔루션은 다음과 같습니다.

select * from (
  SELECT id,
  ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id asc) AS Row
  FROM tbl
) dups
where
dups.Row > 1


답변

중복 될 필드에서 동일한 테이블에 조인 한 다음 id 필드에서 결합 방지 할 수 있습니다. 첫 번째 테이블 별명 (tn1)에서 id 필드를 선택한 후 두 번째 테이블 별명의 id 필드에서 array_agg 함수를 사용하십시오. 마지막으로 array_agg 함수가 제대로 작동하려면 tn1.id 필드를 기준으로 결과를 그룹화합니다. 레코드의 ID와 조인 조건에 맞는 모든 ID의 배열을 포함하는 결과 집합이 생성됩니다.

select tn1.id,
       array_agg(tn2.id) as duplicate_entries,
from table_name tn1 join table_name tn2 on
    tn1.year = tn2.year
    and tn1.sid = tn2.sid
    and tn1.user_id = tn2.user_id
    and tn1.cid = tn2.cid
    and tn1.id <> tn2.id
group by tn1.id;

분명히 하나의 id에 대해 duplicate_entries 배열에있는 id는 결과 집합에 자체 항목을 갖습니다. 이 결과 집합을 사용하여 ‘진실’의 원천이 될 id를 결정해야합니다. 삭제해서는 안되는 하나의 레코드입니다. 아마도 당신은 이런 식으로 할 수 있습니다 :

with dupe_set as (
select tn1.id,
       array_agg(tn2.id) as duplicate_entries,
from table_name tn1 join table_name tn2 on
    tn1.year = tn2.year
    and tn1.sid = tn2.sid
    and tn1.user_id = tn2.user_id
    and tn1.cid = tn2.cid
    and tn1.id <> tn2.id
group by tn1.id
order by tn1.id asc)
select ds.id from dupe_set ds where not exists
 (select de from unnest(ds.duplicate_entries) as de where de < ds.id)

중복이있는 가장 낮은 수의 ID를 선택합니다 (ID가 int PK 증가한다고 가정). 이것들은 당신이 유지할 ID입니다.


답변

더 쉽게하기 위해 열 연도에만 고유 제약 조건을 적용하고 기본 키는 id라는 열이라고 가정합니다.

중복 값을 찾으려면 실행해야합니다.

SELECT year, COUNT(id)
FROM YOUR_TABLE
GROUP BY year
HAVING COUNT(id) > 1
ORDER BY COUNT(id);

위의 sql 문을 사용하면 테이블에 모든 중복 연도가 포함 된 테이블이 생성됩니다. 위해서는 하여 최신 중복 항목을 제외한 모든 중복을 삭제하는 당신은 SQL 문을 위의를 사용해야합니다.

DELETE
FROM YOUR_TABLE A USING YOUR_TABLE_AGAIN B
WHERE A.year=B.year AND A.id<B.id;


답변