Devin.KR

기간과 NULL 필터

100분 안팎

학습 목표

기간 경계와 NULL을 포함한 교통 표에서 분석 대상 행만 반환합니다.

개념

질문의 대상을 WHERE로 옮깁니다

보고서에 9월 1일부터 3일까지 A와 B라고 적었다면 SQL에도 그 조건이 있어야 합니다. WHERE는 원본 행마다 조건을 평가해 대상만 남깁니다. SELECT가 필요한 열을 정한다면 WHERE는 필요한 행을 정합니다. 날짜를 선택 열에서 숨겨도 날짜 조건을 적용할 수 있지만, 검증 단계에서는 날짜도 출력해 경계를 눈으로 확인합니다. 조회가 성공했다는 사실만으로 대상 기간이 맞다고 판단하지 않습니다.

문자열 값은 'A'처럼 작은따옴표로 감쌉니다. IN ('A', 'B')는 A 또는 B에 해당하는 행을 선택합니다. region='A' OR region='B'와 같은 의도를 더 짧게 표현합니다. 지역 목록과 기간 조건을 AND로 연결하면 두 조건을 함께 만족하는 행만 남습니다. 한 조건씩 적용하면서 행 수 변화를 확인하면 대상 밖 지역이 섞인 원인을 찾기 쉽습니다.

기간의 양 끝을 시험합니다

이번 원본 날짜는 YYYY-MM-DD 고정 형식 TEXT입니다. 이 형식의 유효한 날짜끼리는 문자열 비교 순서가 날짜 순서와 맞으므로 date >= '2026-09-01' AND date <= '2026-09-03'으로 양 끝을 포함합니다. BETWEEN '2026-09-01' AND '2026-09-03'도 두 끝을 포함합니다. 시작일 앞날과 종료일 다음 날을 fixture에 넣으면 부등호 하나를 잘못 쓴 문제를 잡을 수 있습니다.

이 규칙을 모든 날짜 문자열에 적용하지 않습니다. 2026-9-2처럼 자리수가 다르거나 09/02/2026처럼 형식이 다르면 먼저 정규화해야 합니다. 이번 로더는 date.fromisoformat으로 날짜 유효성을 확인하고 다시 출력한 문자열과 일치하는지 확인합니다. SQLite의 TEXT 선언만으로 달력상 유효한 날짜가 보장되는 것은 아닙니다. 스키마 선언과 입력 검사는 각각 역할이 있습니다.

시각까지 있는 자료에서는 종료일의 자정을 끝으로 비교하면 마지막 날 낮의 자료가 빠질 수 있습니다. 이 레슨은 하루 단위 날짜만 받으므로 양 끝 포함 비교가 맞습니다. 다음에 타임스탬프를 받으면 시작 시각 이상·다음 날 시작 시각 미만 같은 경계를 별도로 정의합니다. 예제를 외워 바꾸기보다 데이터 사전의 시간 단위와 하루 경계를 확인하는 습관을 갖습니다.

NULL은 0과 다릅니다

A의 9월 3일 빈칸은 NULL로 들어갑니다. NULL은 값이 알려져 있지 않은 상태이며 0은 측정값이 존재하는 상태입니다. vehicle_count IS NOT NULL로 비결측 행을 고르면 B의 9월 2일 0대는 남습니다. vehicle_count > 0을 쓰면 0도 빠져 분석 대상이 달라집니다. 교통량이 없는 날을 보고 싶은지 관측이 없는 날을 보고 싶은지 질문을 먼저 구분합니다.

vehicle_count = NULL은 NULL 행을 찾는 방법이 아닙니다. NULL과의 일반 비교는 참으로 판정되지 않기 때문에 WHERE에 남지 않습니다. NULL을 찾으려면 IS NULL, 값이 있는지 보려면 IS NOT NULL을 씁니다. 반대 조건을 적을 때도 =와 !=를 기계적으로 바꾸지 않습니다. “값이 0이 아니다”와 “값이 알려져 있다”는 서로 다른 조건입니다.

AND와 OR는 괄호로 의도를 고정합니다

region='A' OR region='B' AND date='2026-09-01'이라고 쓰면 AND가 먼저 묶여 A의 모든 날짜가 남을 수 있습니다. (region='A' OR region='B') AND date='2026-09-01'처럼 지역 조건을 괄호로 묶으면 날짜 제한이 두 지역에 함께 적용됩니다. 복잡한 조건은 줄바꿈뿐 아니라 괄호로 그룹을 드러내고, A의 기간 밖 행을 반례로 넣어 확인합니다.

조건을 추가할 때 합계만 보지 않습니다. 빠져야 할 행과 남아야 할 행의 키를 나란히 적습니다. 이번 실습에서는 기간 밖 A, 대상 밖 C, 기간 경계 B, NULL A와 0 B가 각각 반례 역할을 합니다. 결과가 비어 있어도 문법 오류가 아닐 수 있습니다. 필터가 너무 좁은지, 적재 값에 공백이 있는지, NULL 비교를 잘못했는지 한 조건씩 풀어서 확인합니다.

실습과 미션의 제외 정책을 구분합니다

이 레슨의 브라우저 과제는 비결측 행만 반환하므로 A 9월 3일이 없습니다. 뒤 미션의 일별 점검 표는 NULL 그룹을 남겨 관측 누락이 보이게 합니다. 질문 계약의 최종 강수 비교에서는 교통과 날씨가 모두 있는 행을 사용하지만, 지금은 자료 점검 단계입니다. 단계별 목적을 기록하면 비결측 조회의 6행과 일별 점검 표의 6그룹이 숫자만 같고 의미는 다르다는 점을 설명할 수 있습니다.

near "2026": syntax error가 보이면 날짜 따옴표를 확인합니다. no such column: A는 지역 문자열을 따옴표 없이 썼는지 살펴봅니다. SQL 실행 성공 후 0대가 없어졌다면 오류 메시지가 아니라 조건 의미를 읽어야 합니다. 빈 결과를 해결하려고 NULL을 0으로 채우는 대신 선택한 조건이 원래 질문과 맞는지 대조합니다.

조건의 진릿값을 작은 표로 확인합니다

WHERE는 조건이 참인 행만 반환합니다. 거짓뿐 아니라 알 수 없는 결과도 제외됩니다. 예를 들어 vehicle_count != 0은 100과 80을 남기지만 NULL은 남기지 않습니다. 따라서 이 조건을 “0대가 아닌 모든 상태”라고 설명하면 미관측 상태까지 포함한다는 오해가 생깁니다. NULL도 함께 보고 싶다면 vehicle_count != 0 OR vehicle_count IS NULL처럼 두 상태를 명시해야 합니다. 어느 정책이 맞는지는 질문의 대상에 따라 정합니다.

조건을 점검할 때는 날짜·지역·수량을 가진 후보 행마다 포함 여부를 적습니다. A의 시작일 10대는 포함, B의 종료일 0대는 포함, C의 중간 날짜는 제외, A의 기간 안 NULL은 제외라고 예상한 뒤 실행합니다. 특히 0대 행은 비결측 조건과 양수 조건의 차이를 드러냅니다. 합계가 우연히 같더라도 0대 행이 사라지면 관측 건수는 달라지므로 행의 키와 수량을 함께 비교합니다.

기간 조건을 재사용할 때는 보고서 제목만 바꾸지 말고 SQL의 두 경계도 검토합니다. 종료일을 포함하는 일별 조회와 다음 날 자정 미만인 시각 조회를 혼합하지 않습니다. 대상 지역이 추가되면 IN 목록을 갱신하고 새 지역의 기간 밖 행도 시험합니다. 필터의 기대 결과를 먼저 기록해 두면 나중에 조건을 수정했을 때 무엇이 의도적으로 달라졌는지 설명할 수 있습니다.

조건별로 남는 행을 기록합니다

일곱 행 전체에서 지역 조건만 적용하면 A와 B가 모두 대상이므로 일곱 행이 유지됩니다. 기간 조건도 기존 표본에서는 모든 행이 통과합니다. 마지막으로 IS NOT NULL을 적용하면 A의 9월 3일 한 행이 빠져 여섯 행이 됩니다. 조건을 넣었는데 행 수가 그대로인 것은 조건이 실행되지 않았다는 증거가 아닙니다. 모든 입력이 이미 조건 안에 있을 수 있으므로 기간 밖과 대상 밖 자료를 추가한 테스트가 필요합니다.

0대인 B의 9월 2일을 남기는지 별도로 확인합니다. 이 행이 빠졌다면 양수 조건이나 0 제외 조건이 들어갔을 가능성이 있습니다. 반대로 A의 미관측 행이 남았다면 IS NOT NULL 조건의 누락이나 OR 결합을 살펴봅니다. 지역 조건 OR 비결측 조건처럼 서로 다른 목적을 OR로 잇는 경우 대상 밖 지역도 수량이 있으면 통과합니다. 각 조건을 만족하는 행 집합을 먼저 적으면 AND는 교집합, OR는 합집합이라는 차이를 결과로 이해할 수 있습니다.

필터의 제외 사유를 설명합니다

동료에게 결과를 전달할 때는 제외 건수만 적지 말고 적용 조건을 함께 적습니다. 기간 밖, 대상 밖, 미관측은 서로 겹칠 수 있으므로 각각 센 건수를 단순히 더해 전체 제외 수라고 보고하지 않습니다. 조건을 순서대로 적용해 단계별 감소량을 기록하거나, 한 행에 여러 제외 사유가 붙을 수 있다고 명시합니다. 이 과제에서는 원본을 수정하지 않고 조회 조건으로만 대상을 좁힙니다.

최종 쿼리를 읽을 때 지역 목록, 시작일 포함 여부, 종료일 포함 여부, 결측 처리, 정렬을 각각 확인합니다. SELECT에 조건 열이 없더라도 WHERE는 그 열을 참조할 수 있습니다. 결과 표가 요구한 날짜·지역·통행량 순서인지도 확인하되, 열 순서 수정으로 잘못된 필터를 해결할 수는 없습니다. 작은 테스트에서 기대 키 목록을 먼저 쓴 뒤 출력 키와 비교하면 숫자가 우연히 같아 생기는 착각을 줄일 수 있습니다.

따라하기

양 끝 날짜 포함 조회

NULL은 제외하지만 관측된 0은 유지합니다.

SELECT date, region, vehicle_count FROM traffic WHERE region IN ('A','B') AND date BETWEEN '2026-09-01' AND '2026-09-03' AND vehicle_count IS NOT NULL ORDER BY region, date, vehicle_count;

실행 결과

2026-09-01 A 100
2026-09-02 A 80
2026-09-02 A 80
2026-09-01 B 120
2026-09-02 B 0
2026-09-03 B 90

NULL 관측만 찾기

= NULL 대신 IS NULL을 사용합니다.

SELECT region, date FROM traffic WHERE vehicle_count IS NULL ORDER BY region, date;

실행 결과

A 2026-09-03

기간 앞뒤 반례 확인

8월31일·9월4일·지역C는 빠지고 양 끝 날짜와0은 남습니다.

SELECT date, region, vehicle_count FROM traffic WHERE region IN ('A','B') AND date BETWEEN '2026-09-01' AND '2026-09-03' AND vehicle_count IS NOT NULL ORDER BY region, date, vehicle_count;

실행 결과

2026-09-01 A 10
2026-09-03 B 0

확인 문제

실습

traffic에서 A/B, 2026-09-01~03 양 끝 포함, 비결측 통행량 행만 날짜·지역·통행량 순서로 반환합니다. 지역→날짜→통행량 오름차순이며0과 동일 행 반복은 유지합니다.

모범 답안
SELECT date, region, vehicle_count FROM traffic WHERE region IN ('A','B') AND date BETWEEN '2026-09-01' AND '2026-09-03' AND vehicle_count IS NOT NULL ORDER BY region, date, vehicle_count;

더 읽기

면접 질문

  • NULL과 0을 구별하여 필터링하는 방법을 설명해 주세요.
  • AND와 OR를 함께 쓸 때 괄호가 필요한 사례를 설명해 주세요.