Fullmoon System

엑셀 중복값 처리: 같은 주문 두 줄과 고객별 최신 행을 구분하기

AI Editter

고객별 최신 주소만 남기려고 날짜를 내림차순 정렬한 뒤 중복 제거를 했는데, 새로 고침 후 다른 행이 남는다면 선택 규칙부터 점검해야 합니다. 화면에 먼저 보이는 행과 쿼리 처리 과정에서 보존되는 행을 같다고 가정하면 안 됩니다.

Microsoft는 Table.Distinct에서 어떤 중복 행이 남을지 일반적으로 보장되지 않는다고 설명합니다. 쿼리 폴딩과 최적화가 처리에 영향을 줄 수 있기 때문입니다. 관련 동작은 Table.Distinct 공식 문서에 명시돼 있습니다.

이 글에서는 고객코드마다 최신 행을 고르되, 날짜 동률과 값 충돌을 먼저 확인하는 방법을 사용합니다.

중복값 버튼을 누르기 전에 결과 건수를 예상한다

주문번호가 같아도 옵션별로 여러 행이 있는 주문이라면 주문번호 하나만 기준으로 제거하면 정상 품목이 사라집니다. 반대로 모든 업무 열이 동일한 재전송 행은 합계가 두 번 더해질 수 있습니다. 먼저 원본 행 수, 고유 주문 수, 주문별 품목 수를 기록하고 삭제해도 되는 행의 정의를 정합니다. 아래 최신 행 선택은 변경 이력을 현재 상태표로 만드는 경우에 해당하며, 주문 품목 중복 제거에 그대로 적용하지 않습니다.

같은 키가 있다고 같은 종류의 중복은 아니다

고객변경일시수신번호상태
C-012026-10-01 09:00101기존 주소
C-012026-10-03 10:00105새 주소
C-022026-10-03 10:00106서울
C-022026-10-03 10:00107부산
C-03빈칸108대전

가상 예제에서 C-01은 105번을 고르면 됩니다. C-02는 같은 변경일시에 서로 다른 상태가 있습니다. 수신번호가 크다는 이유로 107번이 최신 업무 사실이라고 결론 내릴 수 있는지는 원본 시스템 규칙에 달렸습니다. C-03은 최신 여부를 판단할 날짜가 없습니다.

완전히 같은 이벤트가 중복 전달된 경우, 같은 고객의 서로 다른 변경 이력, 같은 시각의 상충된 값은 각각 따로 처리합니다. 고객코드만 기준으로 중복을 지우면 이 차이가 사라집니다.

먼저 정할 세 가지 규칙

첫째, 최신의 기준을 발생시각으로 할지 수신시각으로 할지 정합니다. 늦게 도착한 과거 수정 내역을 수신시각만 보고 선택하면 오래된 값으로 돌아갈 수 있습니다.

둘째, 같은 시각의 행을 결정할 공식 순번이 있는지 확인합니다. 버전번호가 업무상 증가하는 값이라면 사용할 수 있지만, 파일의 행 번호나 다운로드 순서는 같은 의미가 아닙니다.

셋째, 필요한 값이 빈 최신 행을 어떻게 볼지 정합니다. 주소를 삭제한 이력이라면 빈 값 자체가 최신 상태입니다. 빈칸을 피해 이전 주소를 고르면 삭제 요청이 되살아납니다.

그룹 안에서 정렬하고 한 행 선택하기

다음 코드는 원본 단계에 고객, 변경일시, 수신번호 열이 있고, 변경일시는 datetime, 수신번호는 숫자로 변환돼 있으며 필수 값이 누락되지 않았다는 전제입니다. 고객별 최종 선택 전에 충돌 검사를 완료한 자료에 적용합니다.

let
    그룹 = Table.Group(
        원본,
        {"고객"},
        {{"선택행", each
            Table.FirstN(
                Table.Sort(_, {
                    {"변경일시", Order.Descending},
                    {"수신번호", Order.Descending}
                }),
                1
            )
        }}
    ),
    펼칠열 = List.RemoveItems(Table.ColumnNames(원본), {"고객"}),
    결과 = Table.ExpandTableColumn(그룹, "선택행", 펼칠열, 펼칠열)
in
    결과

전체 표를 미리 정렬했다는 사실에 기대지 않고, 각 고객의 그룹 안에서 선택 순서를 정합니다. 마지막 정렬 열까지 같은 행이 여러 개라면 이 코드만으로 업무상 우선순위가 생기지는 않습니다. 고유한 이벤트 식별자와 충돌 처리 정책이 필요합니다. 그룹화 함수의 동작은 Table.Group 문서를 참고합니다.

충돌 쿼리를 별도로 유지하기

원본을 참조하는 쿼리에서 고객 + 변경일시로 그룹화하고, 각 그룹의 서로 다른 상태 값 개수를 확인합니다. 둘 이상이면 동률 충돌 후보입니다. 상태 열이 여러 개라면 주소·등급·동의 여부 등 판단에 필요한 열 묶음 전체를 비교합니다.

변경일시가 빈 행, 형식 변환에 실패한 행, 고객코드가 빈 행은 최신 행 선택 쿼리에 섞지 않고 예외 목록으로 보냅니다. 오류 행을 제외한 결과를 사용할 때는 해당 고객의 결과가 확정되지 않았다는 사실도 표시해야 합니다.

“최신시각의 MAX를 구한 뒤 원본과 병합”하는 방법도 있습니다. 다만 최신시각에 두 행이 있으면 병합 결과도 두 행이 됩니다. 동률을 보존해 검토하려는 목적에는 맞지만, 고객당 한 행이 필요하다면 추가 규칙이 필요합니다.

새로 고침 결과가 흔들리지 않는지 시험

시험기대 결과
입력 파일의 행 순서 뒤집기같은 선택 규칙이면 동일 결과
C-01에 더 오래된 행 추가선택행 105 유지
C-01에 더 최신인 정상 행 추가선택행 변경
C-02의 동률 충돌 유지자동 확정하지 않고 확인 대상
변경일시를 문자로 훼손변환 오류 목록에 남음
최신 상태를 빈값으로 변경삭제 의미 여부를 정책대로 처리

결과 행 수는 확정 가능한 고유 고객 수와 같아야 합니다. 원본 전체 고객 수와 무조건 같아야 하는 것은 아닙니다. 예외로 빠진 고객이 있다면 별도 목록의 고객 수까지 합쳐서 원본과 대조합니다.

원본 이력은 지우지 않는다

최신 상태표는 조회를 위한 결과입니다. 원본 이력에서 이전 행을 영구 삭제하는 작업과 구별합니다. 선택된 이벤트 번호, 원본 파일명, 선택 기준을 결과에 남기면 “왜 이 주소가 현재값인가”를 설명할 수 있습니다.

Table.Buffer를 사용하는 방법도 공식 문서에 나오지만, 큰 데이터를 무조건 버퍼링하는 것으로 업무 규칙을 대신할 수는 없습니다. 데이터 양과 원본 특성에 따라 성능이 달라질 수 있으므로, 먼저 어떤 행을 선택해야 하는지 정의하고 그 규칙을 같은 입력으로 재현할 수 있는지 확인하는 순서가 좋습니다.

관련 절차: 엑셀 파일 합치기: Power Query 폴더 연결·새로 고침 방법