[sql] PostgreSQL에서 중복 레코드를 찾는 방법
현재 다음과 같은 중복 필드를 허용하는 “user_links”라는 PostgreSQL 데이터베이스 테이블이 있습니다.
year, user_id, sid, cid
고유 제한 그러나 지금 확인하기 위해 제약 조건을 추가 할 찾고, 현재 “ID”라는 첫 번째 필드 인 year
, user_id
, sid
및 cid
모든 고유하지만 중복 값은 이미이 제약 조건을 위반하는 존재하기 때문에 내가 제약 조건을 적용 할 수 없습니다.
모든 중복 항목을 찾는 방법이 있습니까?
답변
기본 아이디어는 카운트 집계와 함께 중첩 쿼리를 사용하는 것입니다.
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;