Postgre에서 중복 레코드를 찾는 방법SQL
나는 포스트그레를 가지고 있습니다.현재 다음 중복 필드를 허용하는 "user_links"라는 SQL 데이터베이스 테이블:
year, user_id, sid, cid
한 제약 "id라는 첫 이지만, "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
출처: "PostgreSQ를 사용하여 중복 행 찾기L" 현명한 솔루션:
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라는 열입니다.
중복된 값을 찾으려면 실행해야 합니다.
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;
중복될 필드의 동일한 테이블에 가입한 다음 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가 PK에서 증가하고 있다고 가정하여 중복되는 가장 낮은 숫자의 ID를 선택합니다.이것들은 당신이 주변에 보관할 신분증일 것입니다.
산드로 위거스에서 영감을 받아, 저는 비슷한 일을 했습니다.
WITH ordered AS (
SELECT id,year, user_id, sid, cid,
rank() OVER (PARTITION BY year, user_id, sid, cid ORDER BY id) AS rnk
FROM user_links
),
to_delete AS (
SELECT id
FROM ordered
WHERE rnk > 1
)
DELETE
FROM user_links
USING to_delete
WHERE user_link.id = to_delete.id;
테스트하려면 다음과 같이 약간 변경합니다.
WITH ordered AS (
SELECT id,year, user_id, sid, cid,
rank() OVER (PARTITION BY year, user_id, sid, cid ORDER BY id) AS rnk
FROM user_links
),
to_delete AS (
SELECT id,year,user_id,sid, cid
FROM ordered
WHERE rnk > 1
)
SELECT * FROM to_delete;
이렇게 하면 삭제할 내용에 대한 개요가 제공됩니다(삭제를 실행할 때 to_delete 쿼리에서 연도, user_id, sid, cid를 유지하는 데 문제가 없지만 필요하지는 않습니다).
SQL 구문을 따르면 중복 행을 확인하는 동안 성능이 향상됩니다.
SELECT id, count(id)
FROM table1
GROUP BY id
HAVING count(id) > 1
당신의 경우, 제약 조건 때문에 중복된 레코드를 삭제해야 합니다.
- 중복된 행 찾기
- 다음 기준으로 구성
created_at
날짜 - 이 경우에는 제가 가장 오래된 것을 보관하고 있습니다. - 다음을 사용하여 레코드 삭제
USING
올바른 행을 필터링하다
WITH duplicated AS (
SELECT id,
count(*)
FROM products
GROUP BY id
HAVING count(*) > 1),
ordered AS (
SELECT p.id,
created_at,
rank() OVER (partition BY p.id ORDER BY p.created_at) AS rnk
FROM products o
JOIN duplicated d ON d.id = p.id ),
products_to_delete AS (
SELECT id,
created_at
FROM ordered
WHERE rnk = 2
)
DELETE
FROM products
USING products_to_delete
WHERE products.id = products_to_delete.id
AND products.created_at = products_to_delete.created_at;
begin;
create table user_links(id serial,year bigint, user_id bigint, sid bigint, cid bigint);
insert into user_links(year, user_id, sid, cid) values (null,null,null,null),
(null,null,null,null), (null,null,null,null),
(1,2,3,4), (1,2,3,4),
(1,2,3,4),(1,1,3,8),
(1,1,3,9),
(1,null,null,null),(1,null,null,null);
commit;
구별 및 예외를 사용하여 작동 설정.
(select id, year, user_id, sid, cid from user_links order by 1)
except
select distinct on (year, user_id, sid, cid) id, year, user_id, sid, cid
from user_links order by 1;
모든 것이 작동하는 것을 제외하고는.ID 직렬이 모든 행을 고유하게 만들기 때문입니다.
(select id, year, user_id, sid, cid from user_links order by 1)
except all
select distinct on (year, user_id, sid, cid)
id, year, user_id, sid, cid from user_links order by 1;
지금까지 null 및 non-null로 작동합니다.
삭제:
with a as(
(select id, year, user_id, sid, cid from user_links order by 1)
except all
select distinct on (year, user_id, sid, cid)
id, year, user_id, sid, cid from user_links order by 1)
delete from user_links using a where user_links.id = a.id returning *;
언급URL : https://stackoverflow.com/questions/28156795/how-to-find-duplicate-records-in-postgresql
'programing' 카테고리의 다른 글
구성 파일에서 서버에 대한 기본 호스트 및 포트 설정 (0) | 2023.05.24 |
---|---|
NodeJS에는 글로벌 모듈/패키지가 필요합니다. (0) | 2023.05.24 |
UI 테스트 실패 - 요소 또는 하위 요소 모두 보안에 중점을 두지 않음텍스트 필드 (0) | 2023.05.24 |
Project-Swift.h를 Object-C 클래스로 가져오는 중...파일을 찾을 수 없음 (0) | 2023.05.24 |
Git에서 HEAD^와 HEAD~의 차이점은 무엇입니까? (0) | 2023.05.24 |