programing

MySQL은 중복된 레코드를 삭제하지만 최신 상태로 유지합니다.

copysource 2022. 9. 29. 22:42
반응형

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

반응형