SQL 책을 펴면 700페이지가 넘어요. 그런데 막상 회사에 출근해서 받는 분석 요청은 대부분 "지난주 매출 얼마야?", "재구매율 어떻게 돼?", "이탈한 사용자 특징은?" 같은 한정된 질문들이에요.
그래서 이 글에서는 주니어 데이터 분석가가 매일 손이 가는 SQL 함수 15개만 골랐어요. 함수마다 한 줄 용도, 실무 예시 SQL, 그리고 자주 하는 실수까지 묶어두었으니, 책 앞장부터 외우기보다 이 15개를 손에 익히는 데 집중해 보세요. 모든 예시는 PostgreSQL과 MySQL 양쪽에 통하는 표준 문법으로 적되, 둘이 갈리는 부분은 따로 표기했어요.
참고로 Stack Overflow 2024 개발자 설문에서 SQL은 전문 개발자의 54.1%가 사용한다고 답한 언어였어요[1]. 분석가 직군에서는 비중이 더 올라가는 게 일반적이고, 사실상 직무 공통어라고 봐도 무방해요.
이미지 자리: SQL 함수 6개 카테고리(집계 / 조건 / 날짜 / 윈도우 / 문자열 / JOIN)를 한눈에 보여주는 카드 그리드. _alt: 데이터 분석가가 매일 쓰는 SQL 함수 6개 카테고리 개요_
1. 집계 함수 — 숫자를 만드는 가장 기본기
① COUNT — 행을 세는 가장 기본 함수
용도: 조건을 만족하는 행이 몇 개인지 세요.
예시:
``sql SELECT COUNT(*) AS total_orders FROM orders WHERE order_date >= '2026-05-01'; ``
자주 하는 실수:
COUNT(*)는 모든 행을 세지만,COUNT(user_id)는user_id가 NULL인 행을 제외해요[2]. 활성 유저 수가 이상하게 작게 나오면 이 차이부터 의심해 보세요.
② SUM / AVG — 합계와 평균
용도: 매출, 평균 객단가, 평균 세션 길이 등 거의 모든 KPI에 들어가요.
예시:
``sql SELECT SUM(amount) AS total_revenue, AVG(amount) AS avg_order_value FROM orders WHERE order_date >= '2026-05-01'; ``
자주 하는 실수:
SUM과AVG는 행이 하나도 없을 때 0이 아니라 NULL을 반환해요[2]. 대시보드에 빈 셀이 뜬다면COALESCE(SUM(amount), 0)처럼 감싸주세요.
③ GROUP BY + HAVING — 그룹별 집계와 집계 후 필터링
용도: "카테고리별 매출", "월별 신규 가입자 수"처럼 그룹별로 자르는 모든 분석.
예시:
``sql SELECT category, SUM(amount) AS revenue FROM orders GROUP BY category HAVING SUM(amount) >= 1000000; ``
자주 하는 실수: 집계 결과로 거를 때
WHERE를 쓰면 에러가 나요. 행 단위 필터는WHERE, 집계 결과 필터는HAVING으로 구분해서 기억하세요.
④ COUNT(DISTINCT ...) — 중복 없이 세기
용도: 활성 사용자(UU), 결제 고객 수처럼 고유 개수를 셀 때.
예시:
``sql SELECT COUNT(DISTINCT user_id) AS active_users FROM events WHERE event_date >= '2026-05-01'; ``
자주 하는 실수: 한 사용자가 하루에 여러 번 이벤트를 발생시켜도 사람 수는 한 명이에요.
COUNT(*)로 세면 활동량이 나오고,COUNT(DISTINCT user_id)로 세야 사람 수가 나와요.
2. 조건 분기 — 데이터를 가공하는 함수
⑤ CASE WHEN — 등급, 세그먼트, 재분류
용도: 점수를 등급으로, 금액을 구간으로, 국가를 권역으로 묶을 때.
예시:
``sql SELECT user_id, CASE WHEN total_amount >= 1000000 THEN 'VIP' WHEN total_amount >= 300000 THEN 'Loyal' ELSE 'New' END AS segment FROM customer_summary; ``
자주 하는 실수: 조건 순서가 중요해요. 첫 번째로 참이 되는 조건만 적용되고 이후는 평가하지 않거든요[5]. 더 좁은 범위(
>= 1000000)를 위에 두지 않으면 모든 사람이 'Loyal'로 떨어져요.
⑥ COALESCE — NULL을 기본값으로 치환
용도: NULL 자리에 0, '미입력', 또는 다른 컬럼의 값을 넣을 때.
예시:
``sql SELECT user_id, COALESCE(nickname, email, '미입력') AS display_name FROM users; ``
공식 정의: "COALESCE는 NULL이 아닌 첫 번째 인자를 반환해요. 모든 인자가 NULL이면 NULL을 반환하고요."[5]
자주 하는 실수:
=비교로 NULL을 잡으려는 시도. SQL에서는NULL = NULL도 NULL이라 비교가 안 돼요. 기본값 처리는 항상COALESCE또는IS NULL로 하세요.
3. 날짜·시간 — 시계열 분석의 기본기
⑦ DATE_TRUNC (PostgreSQL) — 일/주/월 단위로 자르기
용도: "월별 매출 트렌드", "주별 활성 사용자" 등 시계열 그래프의 X축.
시그니처:
date_trunc(field, source)— 첫 인자는 텍스트로'day','week','month','quarter','year'등을 넣어요[3].예시:
``sql SELECT DATE_TRUNC('month', order_date) AS month, SUM(amount) AS revenue FROM orders GROUP BY 1 ORDER BY 1; ``
자주 하는 실수: 단위를 작은따옴표 없이
DATE_TRUNC(month, ...)로 쓰면 식별자로 인식돼 에러가 나요. 항상'month'처럼 따옴표를 둘러주세요.
⑧ DATE_FORMAT (MySQL) — 출력용 날짜 포맷
용도: 보고서나 대시보드에 'YYYY-MM' 등 사람이 읽기 좋은 형식으로 출력.
시그니처:
DATE_FORMAT(date, format)[6].예시:
``sql SELECT DATE_FORMAT(order_date, '%Y-%m') AS month, SUM(amount) AS revenue FROM orders GROUP BY 1; ``
자주 하는 실수: 분(minute) 자리에
%M을 넣는 실수예요.%M은 월 이름(January 등), 분은%i입니다[6]. PostgreSQL에는DATE_FORMAT이 없으니 거기서는TO_CHAR나DATE_TRUNC를 쓰세요.
⑨ EXTRACT — 연/월/일/요일을 숫자로 분리
용도: 요일별 매출, 시간대별 트래픽 등 특정 부분만 뽑아 그룹핑.
예시:
``sql SELECT EXTRACT(HOUR FROM created_at) AS hour_of_day, COUNT(*) AS events FROM events GROUP BY 1 ORDER BY 1; ``
공식 정의: "extract 함수는 연도, 시간 같은 하위 필드를 날짜·시간 값에서 가져와요."[3]
자주 하는 실수: 요일은 PostgreSQL에서
dow(일요일=0) 또는isodow(월요일=1)로 의미가 다르니 보고서 정의와 맞춰서 골라 쓰세요.
4. 윈도우 함수 — 순위와 누적 분석의 무기
윈도우 함수는 행을 합치지 않고 각 행마다 옆 행을 참고해 계산을 더하는 함수예요. ThoughtSpot의 SQL 가이드는 윈도우 함수가 "데이터 손실 없이 비교 분석이 필요한 분석가에게 특히 유용하다"고 정리하고 있어요[8].
⑩ ROW_NUMBER() — 행 번호, 중복 제거 패턴
용도: 그룹별 TOP-N 추출, 가장 최근 한 건만 남기기.
예시 (각 사용자별 가장 최근 주문 1건만):
``sql SELECT FROM ( SELECT o., ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date DESC) AS rn FROM orders o ) t WHERE rn = 1; ``
공식 정의: "파티션 안에서 현재 행의 번호를 1부터 매겨서 돌려줘요."[4]
자주 하는 실수:
PARTITION BY없이 쓰면 전체 테이블이 한 그룹이 돼요. 그룹 단위(예: 사용자별)로 나눌 땐 꼭PARTITION BY를 같이 쓰세요.
⑪ RANK() / DENSE_RANK() — 순위 매기기
용도: 매출 순위, 상품별 인기도. 동률 처리 방식이 다름이 핵심이에요.
차이:
함수 | 동률 결과 (점수 100, 100, 90) | 다음 등수 |
|---|---|---|
| 1, 1, 3 | |
| 1, 1, 2 |
예시:
``sql SELECT product_id, SUM(amount) AS revenue, RANK() OVER (ORDER BY SUM(amount) DESC) AS rank_with_gaps, DENSE_RANK() OVER (ORDER BY SUM(amount) DESC) AS rank_dense FROM orders GROUP BY product_id; ``
자주 하는 실수: 단순히 TOP 10 뽑기에는
ROW_NUMBER가 더 안전해요. 정확히 10개만 필요하다면RANK는 동률 때문에 11개 이상 나올 수 있어요.
⑫ LAG() / LEAD() — 전월 대비, 다음 행동
용도: "지난 달 대비 매출 증감", "다음 결제까지 걸린 시간" 같은 인접 행 비교.
시그니처:
LAG(expr [, offset [, default]]). offset은 기본값 1, default는 기본값 NULL이에요[4][7].예시 (월별 매출의 전월 대비 증감):
``sql SELECT month, revenue, LAG(revenue, 1, 0) OVER (ORDER BY month) AS prev_revenue, revenue - LAG(revenue, 1, 0) OVER (ORDER BY month) AS diff FROM monthly_revenue; ``
자주 하는 실수: default를 안 넣어 첫 행이 NULL이 되고, 그 NULL이 뺄셈에 들어가서 전체 결과가 NULL로 깨지는 패턴. 위 예시처럼
0을 default로 넣어 두면 안전해요.
5. 문자열 함수 — 데이터 정제의 일꾼
⑬ SUBSTRING — 문자열 자르기
용도: 이메일 도메인 추출, 우편번호 앞자리, ID 패턴 분리.
예시 (이메일에서 도메인만):
``sql SELECT SUBSTRING(email FROM POSITION('@' IN email) + 1) AS domain FROM users; ``
자주 하는 실수: 시작 인덱스가 0이 아니라 1부터예요. 그리고 PostgreSQL은
SUBSTRING(str FROM start FOR length), MySQL은SUBSTRING(str, start, length)가 권장 표기라 표기 차이를 한 번 확인하고 가세요.
⑭ REPLACE — 문자열 치환
용도: 공백 제거, 특수문자 정리, '-' 같은 구분자 제거.
예시 (전화번호의 하이픈 제거):
``sql SELECT REPLACE(phone, '-', '') AS phone_clean FROM users; ``
자주 하는 실수: REPLACE는 단순 치환이라 정규식이 안 통해요. 패턴 치환이 필요하면 PostgreSQL은
REGEXP_REPLACE, MySQL 8 이상도REGEXP_REPLACE를 따로 써야 해요.
6. JOIN 패턴 — 분석가의 출퇴근길
⑮ JOIN — INNER vs LEFT, 그리고 흔한 함정
용도: 분리된 테이블(주문, 사용자, 상품)을 합쳐서 한 줄로 보기.
차이:
INNER JOIN: 양쪽에 모두 있는 행만 남아요.LEFT JOIN: 왼쪽 테이블은 모두 남고, 오른쪽에 매칭이 없으면 오른쪽 컬럼이 NULL이에요.예시 (주문이 한 번도 없는 사용자도 같이 보고 싶을 때):
``sql SELECT u.user_id, u.name, COUNT(o.order_id) AS order_count FROM users u LEFT JOIN orders o ON o.user_id = u.user_id GROUP BY u.user_id, u.name; ``
자주 하는 실수:
LEFT JOIN후WHERE o.status = 'paid'처럼 오른쪽 컬럼 조건을WHERE에 넣으면, NULL 행이 같이 빠져 결국 INNER JOIN처럼 동작해요. 오른쪽 테이블에 대한 조건은ON절 안에 넣어 LEFT JOIN의 의미를 보존하세요.
마무리 — 15개로 80%를 처리할 수 있어요
분석 업무는 결국 "세고(집계), 자르고(GROUP BY/CASE/날짜 함수), 비교하고(윈도우), 정제하고(문자열), 합치는(JOIN)" 다섯 동작의 조합이에요. 위 15개 함수가 그 다섯 동작의 핵심이고, 회사에서 매일 받는 분석 요청의 대부분이 이 안에서 풀려요.
처음에는 함수 이름이 헷갈리니까, 실제 쿼리를 써보면서 "이 요청은 어떤 동작이지?"를 스스로 분류하는 연습부터 시작해 보세요. 일주일만 의식적으로 반복해도 손가락이 먼저 움직이게 돼요.
트리업의 스킬 관리 기능으로 보유한 SQL 스킬을 등록하고, 모자란 영역을 채워가는 학습 로드맵으로 연결해 보는 것도 좋아요. 작은 노력들이 모여 큰 성장을 만들어요. 꾸준히 한 줄씩 쌓아가 봐요.