조인과 미매칭 행
75분 안팎
학습 목표
지역 코드 대응표를 거쳐 LEFT JOIN하고 날씨 미매칭 행을 별도로 반환합니다.
개념
남겨야 할 행을 먼저 결정합니다
교통 자료에 날씨가 없을 때 교통 행도 사라지면 누락 규모를 알 수 없습니다. 점검 표는 daily를 왼쪽 기준으로 LEFT JOIN합니다. 오른쪽에서 ON 조건을 만족하는 짝이 있으면 그 값을 붙이고 없으면 오른쪽 열이 NULL인 행을 남깁니다. INNER JOIN은 짝이 있는 행만 남기므로 최종 분석 대상 선택에는 쓸 수 있어도 초기 누락 점검 목적에는 맞지 않습니다.
LEFT JOIN이라고 언제나 왼쪽과 같은 행 수가 되는 것은 아닙니다. 한 교통 행에 오른쪽 짝이 두 개 있으면 두 행이 나옵니다. 이번 레슨에서는 대응표 region과 날씨 지역·날짜가 유일하다는 전제로 결합합니다. 그 전제를 확인하는 조회를 앞에 두면 결과 행 수를 예측할 수 있습니다. 다음 레슨에서는 관측소 때문에 이 전제가 깨지는 상황을 직접 재현합니다.
코드 대응과 날짜를 함께 비교합니다
daily t LEFT JOIN region_map m ON t.region=m.region으로 교통 코드를 날씨 코드로 바꾼 뒤 weather_daily w와 연결합니다. ON m.weather_region=w.weather_region AND t.date=w.date처럼 지역과 날짜를 모두 비교합니다. 날짜 조건을 빼면 같은 지역의 모든 날짜가 붙습니다. A와 WA를 이름이 비슷하다는 이유로 직접 비교하거나 코드 문자열을 잘라 변환하지 않습니다.
t,m,w는 표 별칭입니다. SELECT t.region,t.date라고 적으면 여러 표의 같은 이름 열이 있어도 출처를 알 수 있습니다. ambiguous column name: date는 어떤 표의 날짜인지 지정하지 않았다는 뜻입니다. no such column 오류는 대응표에 없는 열이나 잘못된 별칭을 썼는지 확인합니다. 코드가 문법적으로 성공했는데 전부 미매칭이면 코드 값과 날짜 형식, 앞뒤 공백을 점검합니다.
필터의 위치가 목적을 바꿉니다
결합 뒤 WHERE w.rain_mm > 0을 넣으면 날씨 없는 행은 남지 않습니다. NULL의 비교는 참이 아니어서 WHERE를 통과하지 못합니다. 비 오는 날만 분석하겠다는 의도라면 그 필터가 맞지만 누락 보존 표에는 넣지 않습니다. 오른쪽 후보만 제한하면서 교통 행은 보존하려면 해당 조건을 ON에 넣거나 제한된 날씨 표를 먼저 만듭니다.
미매칭을 찾을 때 w.weather_region IS NULL을 검사합니다. 오른쪽 키는 적재 시 NOT NULL이므로 NULL이면 날씨 행 자체가 없다는 뜻입니다. rain_mm IS NULL만 검사하면 날씨 행이 존재하지만 측정값이 없는 상태와 섞입니다. 대응표 없는 행은 m.region IS NULL로 먼저 찾습니다. 상태별 건수를 나누면 코드 관리 문제와 관측 누락 문제의 담당자도 구분할 수 있습니다.
브라우저 과제는 region,date,reason을 반환하는 미매칭 목록입니다. mapping_missing을 먼저 분류하고 대응이 있어도 날씨 행이 없으면 weather_missing으로 표시합니다. 날씨 행이 있고 rain_mm만 NULL인 경우는 이 목록에 넣지 않습니다. 로컬 미션은 그 경우를 rain_missing 상태로 보존합니다. 서로 다른 출력 목적을 혼동하지 않도록 열 계약을 읽고 제출합니다.
네 행의 결과를 서로 비교합니다
첫 따라하기의 daily는 네 행입니다. A의 두 날짜에는 각각 3과 0의 강수량이 붙습니다. B의 첫 날짜는 날씨 행이 있으나 강수량이 NULL이고, 둘째 날짜는 날씨 행 자체가 없습니다. 첫 조회는 강수량만 보여 주므로 두 B 행의 마지막 열이 모두 NULL입니다. 화면의 같은 값만 보고 같은 원인이라고 판단하지 말고 오른쪽 키가 존재하는지 추가로 조회합니다. 다음 미매칭 조회에서는 B의 둘째 날짜만 반환되는 것이 정상입니다.
대응표를 비운 세 번째 따라하기는 다른 조건을 시험합니다. 날씨를 찾기 전 코드 변환이 실패하므로 A와 C가 모두 mapping_missing입니다. 준비 표에는 A의 같은 날짜가 두 번 들어 있으며 두 입력 행이 그대로 반환됩니다. 이 단계는 입력 키 검사를 대신하지 않습니다. LEFT JOIN의 행 보존과 상태 분류를 관찰하는 예제이고, 실제 파이프라인에서는 중복 키를 먼저 거부합니다. 중복 행까지 보존한다는 동작을 키 유일성 보장으로 오해하지 않습니다.
ON과 WHERE를 작은 표로 검증합니다
A의 강수량 0인 날에 ON 조건으로 rain_mm > 0을 추가하면 오른쪽 후보가 없어지지만 교통 행은 남습니다. 같은 조건을 WHERE에 두면 그 교통 행도 사라집니다. 비 오는 날의 날씨만 붙이고 교통은 모두 남기려는지, 교통 분석 대상도 비 오는 날로 제한하려는지 목적을 먼저 적습니다. 조건의 위치는 성능만의 선택이 아니라 결과의 의미를 결정합니다. 결과가 다르면 SQL 문법보다 어떤 행을 보존하려 했는지부터 되짚습니다.
ON에서 강수 조건을 걸어 탈락한 날씨 행은 원본에 실제로 존재할 수 있습니다. 이때 오른쪽 키 NULL을 원본 관측 누락이라고 부르면 오해가 생깁니다. 이 레슨의 미매칭 목록은 강수량 조건 없이 지역·날짜만으로 연결합니다. 추가 정책을 적용한 목록은 조건 불충족과 원본 부재를 별도 상태로 설명해야 합니다. 조인 결과의 NULL은 현재 ON 조건에 짝이 없다는 뜻이므로 조건을 읽지 않고 원본의 상태를 단정하지 않습니다.
목록의 열과 정렬을 점검합니다
제출 조회는 SELECT에 교통 지역, 교통 날짜, reason을 이 순서로 둡니다. 오른쪽 지역이나 날짜를 선택하면 미매칭 행에서 식별 정보까지 NULL이 됩니다. 왼쪽 식별자를 남겨야 담당자가 어떤 입력을 고칠지 찾을 수 있습니다. ORDER BY t.region,t.date로 목록을 정렬하며 별칭 없는 date는 여러 표의 동명 열과 충돌할 수 있습니다. 정렬은 대응 관계를 고치지는 않지만 누락 목록을 반복 비교하는 데 도움이 됩니다.
빈 교통 입력에서는 반환할 행이 없고 날씨만 존재한다고 해서 새 교통 행을 만들지 않습니다. 반대로 교통은 있고 날씨가 비었으면 대응 코드가 있는 모든 행이 weather_missing입니다. 대응표까지 비었으면 mapping_missing이 먼저 선택됩니다. CASE의 분기 순서를 바꾸면 두 조건을 동시에 만족하는 행의 사유가 달라집니다. 미매칭 조회에는 강수량 NULL인 매칭 행이 포함되지 않는지, 코드 없는 행이 빠지지 않는지 각각 시험합니다.
A와 B가 같은 날씨 코드를 사용하는 경우에도 두 교통 지역은 별개로 남습니다. 대응표의 교통 지역이 유일하고 날씨 요약의 지역·날짜도 유일하다면 같은 오른쪽 값을 참조해도 교통 행이 늘지 않습니다. 이 관계를 잘못된 중복으로 보고 B를 삭제하거나 날씨 코드를 교통 지역에 덮어쓰지 않습니다. 결과의 행 단위는 계속 교통 지역·날짜이며 연결 대상 코드는 그 행에 붙는 속성입니다.
따라하기
대응표 거쳐 결합
아래 준비 표에서 조회를 실행하고 결과를 비교합니다.
SELECT t.region,t.date,w.rain_mm FROM daily t LEFT JOIN region_map m ON t.region=m.region LEFT JOIN weather_daily w ON m.weather_region=w.weather_region AND t.date=w.date ORDER BY t.region,t.date;실행 결과
A 2026-09-01 3 A 2026-09-02 0 B 2026-09-01 NULL B 2026-09-02 NULL
날씨 행 없는 키 찾기
아래 준비 표에서 조회를 실행하고 결과를 비교합니다.
SELECT t.region,t.date,CASE WHEN m.region IS NULL THEN 'mapping_missing' ELSE 'weather_missing' END AS reason FROM daily t LEFT JOIN region_map m ON t.region=m.region LEFT JOIN weather_daily w ON m.weather_region=w.weather_region AND t.date=w.date WHERE m.region IS NULL OR w.weather_region IS NULL ORDER BY t.region,t.date;실행 결과
B 2026-09-02 weather_missing
대응표 없는 상태 찾기
아래 준비 표에서 조회를 실행하고 결과를 비교합니다.
SELECT t.region,t.date,CASE WHEN m.region IS NULL THEN 'mapping_missing' ELSE 'weather_missing' END AS reason FROM daily t LEFT JOIN region_map m ON t.region=m.region LEFT JOIN weather_daily w ON m.weather_region=w.weather_region AND t.date=w.date WHERE m.region IS NULL OR w.weather_region IS NULL ORDER BY t.region,t.date;실행 결과
A 2026-09-01 mapping_missing A 2026-09-01 mapping_missing C 2026-09-02 mapping_missing
확인 문제
실습
daily, region_map(region,weather_region), weather_daily(weather_region,date,rain_mm)가 준비되어 있습니다. 대응표 region 및 날씨 지역·날짜는 유일합니다. 두 LEFT JOIN으로 미매칭만 region,date,reason 순서로 반환합니다. mapping_missing 우선, 다음 weather_missing입니다. 강수값만 NULL인 매칭 행은 제외합니다. 지역·날짜 오름차순입니다.
모범 답안
SELECT t.region,t.date,CASE WHEN m.region IS NULL THEN 'mapping_missing' ELSE 'weather_missing' END AS reason FROM daily t LEFT JOIN region_map m ON t.region=m.region LEFT JOIN weather_daily w ON m.weather_region=w.weather_region AND t.date=w.date WHERE m.region IS NULL OR w.weather_region IS NULL ORDER BY t.region,t.date;
더 읽기
면접 질문
- LEFT JOIN에서 ON과 WHERE에 오른쪽 조건을 둘 때 결과가 어떻게 달라지나요?
- 날씨 행 부재와 강수량 결측을 어떤 열로 구별하나요?