Devin.KR

행과 열 선택

100분 안팎

학습 목표

교통 표에서 날짜·지역·통행량을 선택하고 결과 열과 정렬 순서를 고정합니다.

개념

조회 결과도 계약입니다

동료가 지역별 교통량 파일을 요청했다고 가정합니다. 날짜와 지역이 뒤바뀌거나 실행할 때마다 행 순서가 달라지면 숫자가 맞아도 파일 비교는 실패합니다. 첫 SQL 목표는 데이터를 바꾸는 것이 아니라 필요한 열을 정해진 순서로 보여 주는 것입니다. SELECT는 결과 열, FROM은 읽을 표를 지정합니다. SELECT date, region, vehicle_count FROM traffic;라고 쓰면 원본 열 순서와 관계없이 날짜·지역·통행량 순서로 나옵니다.

SQL은 원하는 결과를 기술하는 언어입니다. 반복문으로 일곱 행을 직접 돌지 않아도 데이터베이스가 표를 읽습니다. SELECT문 끝의 세미콜론은 문장 경계입니다. 열 이름 사이에는 쉼표를 넣고 FROM 뒤에는 표 이름을 씁니다. 줄바꿈은 읽기 편하게 나누는 것이므로 SELECT와 FROM을 각각 줄에 써도 의미는 같습니다. 읽기 전용 조회를 연습하는 동안 UPDATE나 DELETE로 원본을 정리하지 않습니다.

필요한 열을 이름으로 선택합니다

SELECT *는 모든 열을 보여 주므로 탐색에는 편하지만 전달 파일의 규격을 고정하기 어렵습니다. 이후 수집기관이 열을 추가하면 결과 폭이 달라집니다. 날짜·지역·통행량 세 열만 적으면 후속 CSV와 테스트가 기대하는 열 순서를 알 수 있습니다. 브라우저 출력은 열을 공백으로 구분하고 NULL을 문자 NULL로 표시합니다. 헤더가 표시되지 않아도 쿼리의 열 순서가 비교 기준입니다. 로컬 CSV에는 같은 순서의 헤더도 기록합니다.

AS는 결과 열에 별칭을 붙입니다. vehicle_count AS vehicles라고 쓰면 원본 열 이름을 바꾸지 않고 결과 헤더만 vehicles가 됩니다. 계산식에는 역할을 드러내는 별칭을 붙이면 다른 사람이 결과 열을 읽기 쉽습니다. 별칭은 단위 변환이 아닙니다. vehicle_count AS people이라고 이름만 바꾸어도 통행량이 사람 수가 되지 않습니다. 원본 사전의 단위를 유지하며 파일 이름과 헤더에서도 같은 의미를 사용합니다.

행 순서를 명시합니다

ORDER BY region ASC, date ASC는 지역을 먼저 오름차순으로 묶고 같은 지역 안에서 날짜를 오름차순으로 정렬합니다. ASC는 생략할 수 있지만 처음에는 적어서 의도를 확인합니다. SELECT에 날짜를 먼저 써도 ORDER BY에서 지역을 먼저 정할 수 있습니다. 결과 열 순서와 결과 행 순서는 별개입니다. 지역·날짜를 뒤집어 정렬하면 전체 날짜 순으로 A와 B가 교대로 나옵니다.

ORDER BY가 없을 때 저장 순서로 나오는 듯 보여도 그 순서를 결과 계약으로 삼지 않습니다. 테이블 상태나 실행 방식이 달라지면 다른 순서로 반환될 수 있습니다. 동률이 있는 행의 내부 순서도 생각합니다. 이 표에는 A의 9월 2일 80대가 두 번 있어 두 행은 구분되지 않습니다. 값이 다른 동률까지 고정해야 할 때는 vehicle_count처럼 추가 기준을 쓰거나 고유 식별자를 설계합니다. 이번 브라우저 출력은 전체 열까지 정렬하여 다른 값의 순서도 고정합니다.

조회는 중복을 자동으로 없애지 않습니다

일곱 행을 SELECT하면 반복된 80대도 두 번 출력됩니다. 이것은 조회 오류가 아니라 원본 상태가 드러난 것입니다. DISTINCT는 선택한 모든 열의 조합이 같은 결과를 하나로 만듭니다. SELECT DISTINCT region만 실행하면 A와 B 두 코드만 남습니다. 이는 일별 관측을 두 행으로 정제한 것이 아니라 지역 목록을 만든 것입니다. 날짜와 값을 빼고 DISTINCT를 쓴 결과를 후속 통행량 표로 사용하면 안 됩니다.

원본과 조회 결과의 행 수가 같아야 하는지 먼저 질문합니다. 단순 열 선택은 행 수가 유지되지만 DISTINCT는 줄일 수 있습니다. 지금 레슨의 실습은 중복을 포함한 전체 행을 반환합니다. 프로젝트 미션에서는 기존 질문 계약의 완전 일치 중복 제거를 별도 뷰에 명시합니다. 두 단계가 섞이면 원본 합계와 정제 합계의 차이를 설명할 수 없으므로 조회 목적을 나눠 기록합니다.

오류는 이름과 구문부터 읽습니다

no such table: traffic은 아직 테이블을 만들지 않았거나 다른 연결에 적재했다는 뜻입니다. no such column: vehicles는 원본 열 이름과 결과 별칭을 혼동했는지 확인하라는 단서입니다. near "FROM": syntax error는 FROM 바로 앞의 여분 쉼표나 빠진 열 이름을 먼저 살펴봅니다. 숫자가 틀린 결과와 문법 실패를 구분하고, 문법이 맞으면 선택 열과 정렬 조건을 작은 표본으로 대조합니다.

원본과 작업 결과를 구분합니다

앞 모듈의 raw/traffic.csv는 작성팀의 합성 교육 표본입니다. A와 B는 가상 코드이며 실제 지역의 교통 흐름을 주장하지 않습니다. 관측 단위는 지역·날짜, 값의 단위는 대/일입니다. 같은 차량이 여러 번 통과했는지는 알 수 없으므로 통행량을 사람 수나 고유 차량 수라고 설명하지 않습니다. 날씨 표는 다음 모듈에서 결합하며 지금의 SQL 결과는 최종 강수 비교가 아니라 교통 표 자체의 점검입니다.

따라하기 각 단계는 독립된 메모리 SQLite 테이블에서 실행합니다. 아래 SQL 브라우저 실습의 테스트 입력은 표준 입력 텍스트가 아니라 테이블을 만드는 초기화 SQL입니다. 화면이 준비한 traffic 테이블에 SELECT문만 제출합니다. 로컬에서도 재현하려면 Python 3의 sqlite3로 연결하거나 sqlite3 명령줄에서 CREATE TABLE과 INSERT로 같은 일곱 행을 먼저 준비합니다. 프로젝트 ZIP의 pipeline.py는 CSV를 직접 읽으므로 수동으로 적재할 필요가 없습니다.

원본 빈 문자열은 적재 시 SQL NULL로 바뀌고 문자 '0'은 정수 0으로 바뀝니다. SQL에 빈 문자열을 그대로 넣으면 NULL 검사와 COUNT가 의도와 다르게 동작합니다. 결과를 확인할 때 입력 파일의 값과 적재된 자료형을 먼저 구분합니다. 숫자를 문자열로 정렬하면 '100'과 '80'의 비교가 수치 순서와 다를 수 있습니다. 이번 실습은 통행량 INTEGER, 지역과 고정 형식 날짜 TEXT로 준비합니다.

신입에게 권하는 점검 순서는 입력 정체, 선택 열, 대상 행, 묶는 기준, 결과 정렬입니다. 한 번에 여러 조건을 바꾸면 무엇이 수치를 바꿨는지 추적하기 어렵습니다. 먼저 작은 표본에서 예상 행을 써 보고 SQL 결과와 한 줄씩 비교합니다. 잘못된 기대값에 맞춰 원본을 수정하는 대신 조건과 관측 단위를 설명할 수 있는지 확인합니다. 테스트가 통과해도 실제 자료의 수집 품질과 해석의 타당성은 별도로 검토합니다.

따라하기

필요한 열을 같은 순서로 조회

각 단계는 독립 초기화된 일곱 행 traffic에서 실행합니다. 중복과 NULL도 출력됩니다.

SELECT date, region, vehicle_count FROM traffic ORDER BY region, date, vehicle_count;

실행 결과

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

지역 우선과 날짜 우선 비교

앞 출력과 값은 같고 행 순서가 다릅니다.

SELECT date, region, vehicle_count FROM traffic ORDER BY date, region, vehicle_count;

실행 결과

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

지역 목록 조회

세 열 조회와 지역 목록의 관측 단위 차이를 설명합니다.

SELECT DISTINCT region FROM traffic ORDER BY region;

실행 결과

A
B

확인 문제

실습

준비된 traffic(region TEXT, date TEXT, vehicle_count INTEGER)에서 날짜·지역·통행량 순서로 전체 행을 반환합니다. 지역→날짜→통행량 오름차순으로 정렬합니다. NULL과 중복을 유지합니다.

모범 답안
SELECT date, region, vehicle_count FROM traffic ORDER BY region, date, vehicle_count;

더 읽기

면접 질문

  • SELECT * 대신 열 이름을 나열하는 이유와 ORDER BY가 필요한 이유를 설명해 주세요.
  • SELECT DISTINCT region과 전체 행 조회의 관측 단위는 어떻게 다른가요?