같은 키에 여러 파일이 들어올 때 "더 최신 파일이 이기게" 하려고 파일명을 그대로 비교하는 경우가 많다.
.whenMatchedUpdateAll(condition="src.file_nm > tgt.file_nm")
접두사가 완전히 같고 날짜가 zero-padding 돼 있으면 대부분 맞게 동작한다. 문제는 연도 경계다.
| 비교 | 문자열 결과 | 의미상 | |
|---|---|---|---|
01-05 vs 01-10 |
앞이 작다 | 1/5 < 1/10 | 맞다 |
01-30 vs 02-01 |
앞이 작다 | 1/30 < 2/1 | 맞다 |
12-30 2024 - 2025 vs 01-05 2025 - 2026 |
앞이 크다 | 뒤가 최신 | 틀린다 |
파일명 접두사에 지역 코드나 공백 차이가 섞여 있어도 비교가 깨진다.
처리 시각(batch_date) 으로 비교하면 연말 문제는 없어지지만 백필에서 뒤집힌다.
2026-01-01 file_nm=2025-05-10.xlsx 적재 (batch_date=20260101)
2026-02-01 옛 파일 file_nm=2024-12-01.xlsx 재처리 (batch_date=20260201)
→ batch_date 가 더 크므로 조건 통과 → 옛 데이터가 최신을 덮어쓴다
batch_date 는 "언제 처리했는가" 이지 "파일 자체가 언제 것인가" 가 아니다.
의미상 정확한 유일한 방법은 파일명에서 실제 날짜를 추출해 별도 컬럼으로 저장하고 그것으로 dedup 과 MERGE 조건을 거는 것이다.
import re
m = re.search(r'(\d{2})-(\d{2})\s+(\d{4})', file_name)
file_date = f"{m.group(3)}-{m.group(1)}-{m.group(2)}" if m else None
long_df["file_nm"] = file_name
long_df["file_date"] = file_date
from pyspark.sql.window import Window
from pyspark.sql.functions import col, row_number
w = Window.partitionBy("year", "month", "sales_channel", "cust_sku_id") \
.orderBy(col("file_date").desc())
dedup = df.withColumn("rn", row_number().over(w)).filter("rn = 1").drop("rn")
(delta_tgt.alias("tgt")
.merge(dedup.alias("src"), "...키 조건...")
.whenMatchedUpdateAll(condition="src.file_date > tgt.file_date")
.whenNotMatchedInsertAll()
.execute())
챙길 것이 셋 있다. bronze 와 silver 양쪽에 file_date 컬럼을 추가해야 하므로 ALTER TABLE ... ADD COLUMNS 또는 mergeSchema=true 가 필요하다. 패턴 매칭에 실패한 파일은 file_date 가 null 이라 조건을 통과하지 못하므로 최초 INSERT 값이 그대로 남는다(안전한 쪽이다). 기존 데이터는 file_date 가 비어 있어 새 파일이 무조건 이기므로, 한 번은 백필로 채워 주는 편이 좋다.
재처리 결과가 이전과 어떻게 달라졌는지는 Delta time travel 로 본다.
SELECT 'v13 (new)' AS src, COUNT(*) FROM cat.sch.tbl VERSION AS OF 13
UNION ALL
SELECT 'v11 (old)', COUNT(*) FROM cat.sch.tbl VERSION AS OF 11;
WITH new_t AS (SELECT * FROM cat.sch.tbl VERSION AS OF 13),
old_t AS (SELECT * FROM cat.sch.tbl VERSION AS OF 11)
SELECT * FROM new_t
EXCEPT
SELECT * FROM old_t;
키만 남기고 비교하면 "새로 생긴 행 / 사라진 행" 이, 전체 컬럼으로 비교하면 "값이 바뀐 행" 까지 잡힌다. 두 방향(new EXCEPT old, old EXCEPT new) 을 모두 봐야 한다.