Skill Roadmap

데이터 분석가가 매일 쓰는 SQL 함수 TOP 15 — 실무에서 검증된 쿼리 모음

주니어 데이터 분석가가 매일 손이 가는 SQL 함수 15개를 모았어요. 집계, 조건 분기, 날짜·시간, 윈도우 함수, 문자열, JOIN까지 — 각 함수의 용도, 실무 예시 SQL, 자주 하는 실수를 PostgreSQL·MySQL 기준으로 정리했어요.
2026.05.15
데이터 분석가가 매일 쓰는 SQL 함수 TOP 15 — 실무에서 검증된 쿼리 모음

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'; ``

  • 자주 하는 실수: SUMAVG는 행이 하나도 없을 때 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_CHARDATE_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)

다음 등수

RANK()

1, 1, 3

건너뜀 (with gaps)[4][7]

DENSE_RANK()

1, 1, 2

안 건너뜀 (without gaps)[4][7]

  • 예시:

``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 JOINWHERE o.status = 'paid'처럼 오른쪽 컬럼 조건을 WHERE에 넣으면, NULL 행이 같이 빠져 결국 INNER JOIN처럼 동작해요. 오른쪽 테이블에 대한 조건은 ON 절 안에 넣어 LEFT JOIN의 의미를 보존하세요.


마무리 — 15개로 80%를 처리할 수 있어요

분석 업무는 결국 "세고(집계), 자르고(GROUP BY/CASE/날짜 함수), 비교하고(윈도우), 정제하고(문자열), 합치는(JOIN)" 다섯 동작의 조합이에요. 위 15개 함수가 그 다섯 동작의 핵심이고, 회사에서 매일 받는 분석 요청의 대부분이 이 안에서 풀려요.

처음에는 함수 이름이 헷갈리니까, 실제 쿼리를 써보면서 "이 요청은 어떤 동작이지?"를 스스로 분류하는 연습부터 시작해 보세요. 일주일만 의식적으로 반복해도 손가락이 먼저 움직이게 돼요.

트리업의 스킬 관리 기능으로 보유한 SQL 스킬을 등록하고, 모자란 영역을 채워가는 학습 로드맵으로 연결해 보는 것도 좋아요. 작은 노력들이 모여 큰 성장을 만들어요. 꾸준히 한 줄씩 쌓아가 봐요.


출처

데이터 분석
실무 쿼리
데이터 분석가
PostgreSQL
MySQL
윈도우 함수
주니어 분석가
SQL
Updated 2026.05.08

Recommended for you

  • 인턴 vs 개인 프로젝트 vs 자격증, 대학생이 집중해야 할 것은?
    Career
    대학생 취업 준비, 인턴·개인 프로젝트·자격증 중 무엇부터 해야 할까요? 경총·사람인·캐치 데이터로 채용 시장이 보는 진짜 평가 요소와 직무별 우선순위 프레임을 정리했어요.
  • PM 연봉 가이드 - 연차별 시장 데이터와 협상 팁
    Career
    잡코리아·원티드·사업보고서 데이터를 종합한 PM/PO 연차별 평균과 네카라쿠배 빅테크 평균, 협상에 바로 쓰는 5가지 팁까지 한 번에 정리했어요.
  • PM 면접 질문 TOP 10 — 제품 감각을 보여주는 답변법
    Interview
    PM 면접에서 자주 나오는 10개 질문을 5개 카테고리로 정리하고, CIRCLES·AARRR·RICE·STAR 같은 프레임워크로 답변 구조까지 알려드려요.
  • 시니어 개발자 이직 면접 - 시스템 디자인 인터뷰 준비법
    Interview
    시스템 디자인 인터뷰는 정답을 외우는 시험이 아니에요. 시니어 개발자 이직 면접에서 면접관이 보는 시그널, 검증된 4단계 프레임워크, 4주 실전 준비 루틴까지 한 번에 정리했어요.
  • Staff Engineer가 되려면? 시니어 이후 커리어 패스
    Career
    시니어 개발자 다음 커리어가 막막하신가요? 매니저 트랙 말고 Staff Engineer라는 길이 있어요. Will Larson의 4가지 아키타입과 Senior 대비 41% 높은 보상 데이터, 한국 시장 현실까지 정리해드릴게요.
  • 프론트엔드 개발자 면접 질문 TOP 10 (주니어 합격을 가르는 핵심 토픽)
    Interview
    한국 프론트엔드 면접에서 반복되는 질문 10개를 4개 카테고리로 묶었어요. 호이스팅, CORS, Virtual DOM, Core Web Vitals까지 면접관이 보려는 핵심 포인트와 답변 흐름을 한 번에 정리했어요.