MySQL은 중복된 레코드를 삭제하지만 최신 상태로 유지합니다.
나는 독특하다.id
★★★★★★★★★★★★★★★★★」email
[ ]이렇게 하다이메일이 중복됩니다.된 이메일 중 주소를 .id
(일부러)
어떻게 하면 좋을까요?
을 상상하다test
에는 다음 데이터가 포함되어 있습니다.
select id, email
from test;
ID EMAIL
---------------------- --------------------
1 aaa
2 bbb
3 ccc
4 bbb
5 ddd
6 eee
7 aaa
8 aaa
9 eee
그래서 우리는 모든 반복되는 이메일을 찾아서 모두 삭제해야 합니다. 하지만 최신 아이디는 삭제해야 합니다.
「」는,aaa
,bbb
★★★★★★★★★★★★★★★★★」eee
아이디 1, 7, 2, 6입니다.
이를 위해서는 먼저 모든 반복 메일을 찾아야 합니다.
select email
from test
group by email
having count(*) > 1;
EMAIL
--------------------
aaa
bbb
eee
그런 다음 이 데이터 집합에서 반복되는 각 이메일의 최신 ID를 찾아야 합니다.
select max(id) as lastId, email
from test
where email in (
select email
from test
group by email
having count(*) > 1
)
group by email;
LASTID EMAIL
---------------------- --------------------
8 aaa
4 bbb
9 eee
마지막으로 LASTID보다 작은 ID를 가진 모든 이메일을 삭제할 수 있습니다.해결책은 다음과 같습니다.
delete test
from test
inner join (
select max(id) as lastId, email
from test
where email in (
select email
from test
group by email
having count(*) > 1
)
group by email
) duplic on duplic.email = test.email
where test.id < duplic.lastId;
현재 이 컴퓨터에 mySql이 설치되어 있지 않지만 작동해야 합니다.
갱신하다
위의 삭제는 가능하지만 보다 최적화된 버전을 찾았습니다.
delete test
from test
inner join (
select max(id) as lastId, email
from test
group by email
having count(*) > 1) duplic on duplic.email = test.email
where test.id < duplic.lastId;
1, 7, 2, 6과 같이 가장 오래된 중복을 삭제하는 것을 볼 수 있습니다.
select * from test;
+----+-------+
| id | email |
+----+-------+
| 3 | ccc |
| 4 | bbb |
| 5 | ddd |
| 8 | aaa |
| 9 | eee |
+----+-------+
또 다른 버전은 Rene Limon에 의한 삭제입니다.
delete from test
where id not in (
select max(id)
from test
group by email)
이 방법을 사용해 보세요.
DELETE t1 FROM test t1, test t2
WHERE t1.id > t2.id AND t1.email = t2.email
올바른 방법은
DELETE FROM `tablename`
WHERE `id` NOT IN (
SELECT * FROM (
SELECT MAX(`id`) FROM `tablename`
GROUP BY `name`
)
)
DELETE
FROM
`tbl_job_title`
WHERE id NOT IN
(SELECT
*
FROM
(SELECT
MAX(id)
FROM
`tbl_job_title`
GROUP BY NAME) tbl)
개정판 및 동작판!!!감사합니다 @Gaurav
id 값이 가장 작은 행을 유지하는 경우:
DELETE n1 FROM 'yourTableName' n1, 'yourTableName' n2 WHERE n1.id > n2.id AND n1.email = n2.email
id 값이 가장 높은 행을 유지하는 경우:
DELETE n1 FROM 'yourTableName' n1, 'yourTableName' n2 WHERE n1.id < n2.id AND n1.email = n2.email
또는 이 쿼리가 도움이 될 수도 있습니다.
DELETE FROM `yourTableName`
WHERE id NOT IN (
SELECT * FROM (
SELECT MAX(id) FROM yourTableName
GROUP BY name
)
)
최적화된 버전은 달콤하고 우아한 코드 1개로 DATETIME 컬럼에서 비교해도 매력적으로 작용합니다.각 직원의 최신 계약 종료일을 검색하기 위해 스크립트에서 사용한 것입니다.아이디:
DELETE CurrentContractData
FROM CurrentContractData
INNER JOIN (
SELECT
EmployeeID,
PeriodofPerformanceStartDate,
max(PeriodofPerformanceEndDate) as lastDate,
ContractID
FROM CurrentContractData
GROUP BY EmployeeID
HAVING COUNT(*) > 1) Duplicate on Duplicate.EmployeeID = CurrentContractData.EmployeeID
WHERE CurrentContractData.PeriodofPerformanceEndDate < Duplicate.lastDate;
감사합니다!
저는 개인적으로 상위 두 개의 투표 답변에 어려움을 겪었습니다.가장 깨끗한 솔루션은 아니지만 임시 테이블을 사용하여 MySQL이 동일한 테이블에 참여함으로써 삭제하는 문제를 방지할 수 있습니다.
CREATE TEMPORARY TABLE deleteRows;
SELECT MIN(id) as id FROM myTable GROUP BY myTable.email;
DELETE FROM myTable
WHERE id NOT IN (SELECT id FROM deleteRows);
DELIMITER //
CREATE FUNCTION findColumnNames(tableName VARCHAR(255))
RETURNS TEXT
BEGIN
SET @colNames = "";
SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.columns
WHERE TABLE_NAME = tableName
GROUP BY TABLE_NAME INTO @colNames;
RETURN @colNames;
END //
DELIMITER ;
DELIMITER //
CREATE PROCEDURE deleteDuplicateRecords (IN tableName VARCHAR(255))
BEGIN
SET @colNames = findColumnNames(tableName);
SET @addIDStmt = CONCAT("ALTER TABLE ",tableName," ADD COLUMN id INT AUTO_INCREMENT KEY;");
SET @deleteDupsStmt = CONCAT("DELETE FROM ",tableName," WHERE id NOT IN
( SELECT * FROM ",
" (SELECT min(id) FROM ",tableName," group by ",findColumnNames(tableName),") AS tmpTable);");
set @dropIDStmt = CONCAT("ALTER TABLE ",tableName," DROP COLUMN id");
PREPARE addIDStmt FROM @addIDStmt;
EXECUTE addIDStmt;
PREPARE deleteDupsStmt FROM @deleteDupsStmt;
EXECUTE deleteDupsStmt;
PREPARE dropIDStmt FROM @dropIDStmt;
EXECUTE dropIDstmt;
END //
DELIMITER ;
테이블에 기존 고유 ID를 사용하지 않고 테이블의 모든 중복 레코드를 삭제하기 위해 만든 멋진 저장 프로시저입니다.
CALL deleteDuplicateRecords("yourTableName");
테이블 내의 여러 열을 기준으로 중복된 레코드를 삭제하고 싶기 때문에 이 접근법이 효과가 있었습니다.
순서 1 - 중복된 레코드에서 최대 ID 또는 고유 ID를 가져옵니다.
select * FROM ( SELECT MAX(id) FROM table_name
group by travel_intimation_id,approved_by,approval_type,approval_status having
count(*) > 1
스텝 2 - 테이블에서 단일 레코드의 ID 가져오기
select * FROM ( SELECT id FROM table_name
group by travel_intimation_id,approved_by,approval_type,approval_status having
count(*) = 1
순서 3 - 위의 2개의 쿼리를 삭제에서 제외합니다.
DELETE FROM `table_name`
WHERE
id NOT IN (paste step 1 query) a //to exclude duplicate records
and
id NOT IN (paste step 2 query) b // to exclude single records
최종 쿼리:-
DELETE FROM `table_name`
WHERE id NOT IN (
select * FROM ( SELECT MAX(id) FROM table_name
group by travel_intimation_id,approved_by,approval_type,approval_status having
count(*) > 1) a
)
and id not in (
select * FROM ( SELECT id FROM table_name
group by travel_intimation_id,approved_by,approval_type,approval_status having
count(*) = 1) b
);
이 쿼리에 의해 중복된 레코드만 삭제됩니다.
언급URL : https://stackoverflow.com/questions/6107167/mysql-delete-duplicate-records-but-keep-latest
'programing' 카테고리의 다른 글
ajax의 시간 초과 설정(jQuery) (0) | 2022.09.29 |
---|---|
matplotlib를 사용하여 while loop에서 실시간 플롯을 작성하려면 어떻게 해야 합니까? (0) | 2022.09.29 |
Java 스태틱콜은 비 스태틱콜보다 비싼가요, 아니면 저렴한가요? (0) | 2022.09.29 |
Python에서 함수를 코멘트하는 적절한 방법은 무엇입니까? (0) | 2022.09.29 |
gcc에 루프를 풀도록 지시합니다. (0) | 2022.09.25 |