Skip to content

Instantly share code, notes, and snippets.

@shane-shim
Last active February 24, 2026 08:30
Show Gist options
  • Select an option

  • Save shane-shim/4b9d73b54ac0ead27aabd25df85cbe54 to your computer and use it in GitHub Desktop.

Select an option

Save shane-shim/4b9d73b54ac0ead27aabd25df85cbe54 to your computer and use it in GitHub Desktop.
마케터를 위한 SQL 기초 완벽 가이드 — 기본 문법부터 시계열 분석, 실무 쿼리 패턴, 치트시트까지

마케터를 위한 SQL 기초 완벽 가이드

데이터 리터러시의 시작 — SQL로 직접 데이터를 꺼내고, 분석하고, 시각화하는 실무 교육자료


목차

  1. 데이터 리터러시와 SQL 개요
  2. SQL 기본 문법
  3. SQL 심화 문법
  4. 데이터 시각화
  5. 시계열 분석과 인사이트 도출
  6. 마케터 실무 쿼리 패턴
  7. SQL 치트시트

1. 데이터 리터러시와 SQL 개요

데이터 활용 흐름

데이터 수집 → 전처리 → 가공 → 분석 → 시각화 → 인사이트 도출

관계형 데이터베이스의 기본 구조

데이터베이스는 **행(Row)**과 **열(Column)**로 구성된 테이블 형태로 데이터를 저장한다.

용어 설명 엑셀 비유
데이터베이스 데이터를 저장하는 전체 공간 엑셀 파일
테이블 특정 주제의 데이터 집합 시트(Sheet)
행(Row) 하나의 레코드(데이터 한 건) 가로 한 줄
열(Column) 데이터의 속성(필드) 세로 한 줄

SQL의 종류

종류 설명 대표 명령어
DML (데이터 조작어) 데이터를 검색·추가·수정·삭제 SELECT, INSERT, UPDATE, DELETE
DDL (데이터 정의어) 테이블 구조를 생성·변경·삭제 CREATE, ALTER, DROP
DCL (데이터 제어어) 접근 권한을 관리 GRANT, REVOKE

마케터가 가장 많이 사용하는 것은 DML의 SELECT (데이터 조회)


쿼리 작성 기본 규칙

  • 구문 간 띄어쓰기 필수
  • 대소문자 구분 없음 (관례상 키워드는 대문자)
  • 별칭(AS)에 띄어쓰기 불가 → 언더바(_) 사용
  • 문자열·날짜 값은 작은따옴표(') 감싸기

2. SQL 기본 문법

쿼리 실행 순서 (필수 암기)

SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY

이 순서를 정확히 지켜야 오류가 발생하지 않는다.


2-1. SELECT & FROM — 데이터 조회

-- 모든 컬럼 검색
SELECT * FROM 테이블명;

-- 특정 컬럼만 검색
SELECT order_date, order_id, order_mode
FROM 테이블명;

AS — 별칭 지정

컬럼명이나 테이블명을 짧고 읽기 쉽게 변경한다.

SELECT
    order_date AS ord_dt,       -- 컬럼 별칭
    order_id,
    order_mode
FROM oe_orders AS t1;             -- 테이블 별칭

2-2. WHERE — 조건 필터링

엑셀의 '필터'와 같은 역할. 원본 테이블에서 원하는 데이터만 추출한다.

주요 연산자

연산자 사용법 설명
= / != WHERE status = 'active' 같다 / 같지 않다
> / >= / < / <= WHERE price >= 10000 비교 연산
AND WHERE A = 1 AND B = 2 모든 조건 충족
OR WHERE A = 1 OR B = 2 하나라도 충족
BETWEEN A AND B WHERE idx BETWEEN 3000 AND 4000 A 이상 B 이하
IN (리스트) WHERE idx IN ('12535', '4000') 여러 값 중 일치
LIKE WHERE grade LIKE '%마케팅%' 패턴 매칭 (와일드카드)
IS NULL WHERE hotel_idx IS NULL 값이 비어있음
IS NOT NULL WHERE hotel_idx IS NOT NULL 값이 존재함

LIKE 와일드카드

패턴 의미 예시
%keyword% keyword를 포함하는 LIKE '%마케팅%'
keyword% keyword로 시작하는 LIKE '서울%'
%keyword keyword로 끝나는 LIKE '%1'
_ 한 글자 대체 LIKE '_A' → 2글자, A로 끝남

IS NULL 주의사항

NULL은 숫자 0이 아니다. 데이터 자체가 없는 상태이므로 = NULL로 비교할 수 없고, 반드시 IS NULL을 사용해야 한다.

-- 여러 조건을 괄호로 묶어 로직 순서를 명확하게
SELECT *
FROM orders
WHERE (region = '서울' OR region = '경기')
  AND order_date >= '2024-01-01';

2-3. GROUP BY — 그룹화 + 집계 함수

데이터를 특정 컬럼 기준으로 묶어 그룹화하고, 집계 함수로 연산한다.

집계 함수

함수 설명 NULL 처리
COUNT() 행의 개수 NULL 포함
SUM() 합계 NULL 제외
AVG() 평균 NULL 제외 (주의!)
MAX() 최댓값 NULL 제외
MIN() 최솟값 NULL 제외

AVG 주의: NULL을 제외하고 평균을 구하므로, NULL을 0으로 포함해서 평균내려면 별도 처리 필요

SELECT
    category,
    COUNT(*) AS order_cnt,
    SUM(ord_price) AS total_price,
    AVG(ord_price) AS avg_price
FROM orders
WHERE region = '서울특별시'
GROUP BY category;

2-4. HAVING — 집계 결과 필터링

GROUP BY 이후 집계된 결과에 조건을 걸 때 사용한다.

WHERE vs HAVING: WHERE는 원본 테이블 필터링, HAVING은 집계 결과 필터링. WHERE 안에는 SUM() > 100 같은 집계 함수 조건을 쓸 수 없다.

SELECT
    category,
    SUM(ord_price) AS total_price
FROM orders
GROUP BY category
HAVING SUM(ord_price) > 100000;  -- 집계 결과에 조건 적용

2-5. ORDER BY — 정렬

옵션 의미 비고
ASC 오름차순 (작은 → 큰) 기본값, 생략 가능
DESC 내림차순 (큰 → 작은) 명시 필수
SELECT category, SUM(ord_price) AS total_price
FROM orders
GROUP BY category
ORDER BY total_price DESC;  -- 금액 큰 순으로 정렬

-- 숫자로 간편하게 지정 가능 (SELECT의 n번째 컬럼)
ORDER BY 2 DESC;

-- 다중 정렬
ORDER BY 1 ASC, 2 DESC;

종합 예제 — 모든 구문 활용

SELECT
    month,
    category,
    SUM(ord_price) AS total_price
FROM reservation_rec_single               -- 1. 대상 테이블
WHERE order_date >= '2020-01-01'          -- 2. 원본 필터링
GROUP BY month, category                  -- 3. 그룹화
HAVING SUM(ord_price) > 100              -- 4. 집계 결과 필터링
ORDER BY 1;                               -- 5. 정렬

3. SQL 심화 문법

3-1. CASE WHEN — 조건 분기

조건에 따라 데이터를 분류하거나 새로운 값을 부여한다. 엑셀의 IF 함수와 유사.

SELECT
    customer_id,
    CASE
        WHEN age < 10 THEN '10대 미만'
        WHEN age BETWEEN 10 AND 19 THEN '10대'
        WHEN age BETWEEN 20 AND 29 THEN '20대'
        WHEN age BETWEEN 30 AND 39 THEN '30대'
        WHEN age BETWEEN 40 AND 49 THEN '40대'
        ELSE '50대 이상'
    END AS age_group
FROM customers;

3-2. CAST — 데이터 형변환

컬럼의 데이터 타입을 변경한다.

변환 타입 설명
STRING 문자열
DATE 날짜
INT64 정수
FLOAT64 실수
SELECT CAST(order_date AS STRING) AS date_str
FROM orders;

3-3. 문자열 함수 — LEFT, RIGHT, SUBSTR

함수 설명 예시
LEFT(col, n) 왼쪽부터 n글자 추출 LEFT('2024-03-15', 4)'2024'
RIGHT(col, n) 오른쪽부터 n글자 추출 RIGHT('2024-03-15', 2)'15'
SUBSTR(col, start, n) start 위치부터 n글자 추출 SUBSTR('2024-03-15', 6, 2)'03'
-- 날짜에서 연도만 추출
SELECT SUBSTR(CAST(order_date AS STRING), 1, 4) AS yyyy
FROM orders;

3-4. 윈도우 함수 — LAG, LEAD

행(Row) 간 관계를 연산. 과거/미래 행의 값을 현재 행으로 가져온다.

함수 설명
LAG(col, n) OVER (ORDER BY ...) n번째 이전 행의 값
LEAD(col, n) OVER (ORDER BY ...) n번째 이후 행의 값
-- 전월 매출과 당월 매출을 나란히 보기
SELECT
    month,
    revenue,
    LAG(revenue, 1) OVER (ORDER BY month) AS prev_month_revenue
FROM monthly_sales;

3-5. WITH 절 — 임시 테이블

복잡한 쿼리에서 동일한 블록을 반복하지 않도록 임시 테이블을 생성한다. 쿼리 실행 시에만 존재하고 사라진다.

-- 단일 WITH
WITH total_order AS (
    SELECT order_type, order_id
    FROM oe_orders
)
SELECT order_type, COUNT(order_id) AS cnt
FROM total_order
GROUP BY order_type;

-- 다중 WITH (콤마로 연결)
WITH
  table_a AS (SELECT ...),
  table_b AS (SELECT ...)
SELECT *
FROM table_a
JOIN table_b ON ...;

3-6. JOIN — 테이블 가로 연결

두 개 이상의 테이블을 **공통 키(Primary Key)**를 기준으로 가로로 병합한다.

JOIN 유형 비교

JOIN 유형 결과
INNER JOIN 양쪽 테이블에 공통으로 존재하는 값
LEFT JOIN 왼쪽 테이블 전체 + 오른쪽에서 매칭되는 값
RIGHT JOIN 오른쪽 테이블 전체 + 왼쪽에서 매칭되는 값
FULL JOIN 양쪽 테이블의 모든 데이터
INNER JOIN:      LEFT JOIN:       FULL JOIN:
  ┌───┐           ┌───┐           ┌───┐
  │ ∩ │           │ A ∪∩│          │A ∪ B│
  └───┘           └───┘           └───┘
-- LEFT JOIN 예시
SELECT
    t1.order_id,
    t1.customer_id,
    t2.customer_name
FROM orders AS t1
LEFT JOIN customers AS t2
    ON t1.customer_id = t2.customer_id;

주의 (VLOOKUP과의 차이): JOIN은 1:N 매칭이 가능하므로, 데이터가 중복 뻥튀기될 수 있다. 거래액 등 합계를 구할 때 반드시 중복 여부를 확인할 것!


3-7. UNION / UNION ALL — 테이블 세로 연결

JOIN이 가로 연결이라면, UNION은 세로 연결이다.

연산자 설명
UNION ALL 모든 결과를 그대로 합침 (중복 허용)
UNION 중복 제거 후 합침
SELECT channel, date, ad_cost FROM campaign_a
UNION ALL
SELECT channel, date, ad_cost FROM campaign_b;

규칙: 위아래 쿼리의 컬럼 타입, 순서, 개수가 모두 동일해야 한다. 컬럼명은 달라도 되며, 결과는 첫 번째 쿼리의 컬럼명을 따른다.


4. 데이터 시각화

시각화의 목적

  • 분석 결과를 한눈에 파악하게 하고 스토리를 효과적으로 전달
  • 전달하고 싶은 부분을 강조하고 분석가의 의도를 담아냄
  • 잘못된 시각화는 인지적 오류를 유발할 수 있으므로 주의

목적에 따른 차트 선택

분석 목적 추천 차트 예시
구성 비율 비교 파이/도넛, 100% 누적 열 카테고리별 매출 비중
항목 간 크기 비교 막대(Bar)/열 그래프 채널별 주문 수 비교
시간 추이/트렌드 선(Line) 그래프 월별 매출 추이
크기 + 추이 동시 콤보 차트 (막대 + 선) 월별 매출(막대) + 전환율(선)

구글 스프레드시트 시각화 워크플로우

  1. SQL 쿼리 결과를 스프레드시트로 내보내기
  2. 데이터 범위 선택 → 삽입 > 차트
  3. 차트 편집기에서 X축/Y축 설정
  4. 콤보 차트, 데이터 라벨, 색상 등 세부 조정
  5. 피벗 테이블: 데이터 > 피벗 테이블로 요약 분석 (SQL의 GROUP BY와 유사한 역할)

5. 시계열 분석과 인사이트 도출

시계열 분석이란?

시간의 흐름에 따라 데이터를 순서대로 나열하여 트렌드를 모니터링하는 분석 기법.

핵심 가정: 과거의 트렌드가 미래에도 지속된다고 가정하고, 현재를 분석하며 미래를 예측한다.

변동성의 두 가지 유형

유형 설명 예시
규칙적 변동성 장기 추세, 계절 순환 여름 성수기 매출 상승
불규칙 변동성 외부 요인에 의한 일시적 변화 프로모션, 이벤트, 코로나

연도별/월별 매출 분석 쿼리

SELECT
    EXTRACT(YEAR FROM dt) AS year,
    EXTRACT(MONTH FROM dt) AS month,
    SUM(purchase_amount) AS amount
FROM total_purchase_log
GROUP BY 1, 2
ORDER BY 1, 2;

전년 동월 대비 매출 증감률 분석

WITH 절 + CASE WHEN으로 연도별 매출을 가로 전개(Pivot)한 뒤 증감률을 계산한다.

WITH order_raw AS (
    SELECT
        EXTRACT(YEAR FROM dt) AS year,
        EXTRACT(MONTH FROM dt) AS month,
        SUM(purchase_amount) AS amount
    FROM total_purchase_log
    GROUP BY 1, 2
)
SELECT
    month,
    SUM(CASE WHEN CAST(year AS STRING) = '2023' THEN amount END) AS amount_2023,
    SUM(CASE WHEN CAST(year AS STRING) = '2024' THEN amount END) AS amount_2024,
    ROUND(
        SUM(CASE WHEN CAST(year AS STRING) = '2024' THEN amount END)
        / SUM(CASE WHEN CAST(year AS STRING) = '2023' THEN amount END)
        * 100
    ) - 100 AS yoy_growth_rate
FROM order_raw
GROUP BY 1
ORDER BY 1;

6. 마케터 실무 쿼리 패턴

패턴 1: 고객 세그먼테이션

CASE WHEN으로 고객을 연령대/등급/행동별로 분류하여 세그먼트 분석

SELECT
    CASE
        WHEN age BETWEEN 20 AND 29 THEN '20대'
        WHEN age BETWEEN 30 AND 39 THEN '30대'
        ELSE '기타'
    END AS age_group,
    gender,
    COUNT(*) AS customer_cnt,
    SUM(order_amount) AS total_amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY 1, 2
ORDER BY 4 DESC;

패턴 2: 광고/프로모션 성과 분석

JOIN + 집계로 일자별 광고 효율(광고당 주문수) 산출

SELECT
    a.date,
    COUNT(DISTINCT a.ad_id) AS ad_cnt,
    COUNT(DISTINCT o.order_id) AS order_cnt,
    ROUND(COUNT(DISTINCT o.order_id) / COUNT(DISTINCT a.ad_id), 2) AS orders_per_ad
FROM ads a
LEFT JOIN orders o ON a.date = o.order_date AND a.channel = o.channel
WHERE a.ad_id IN (2, 3, 4, 7)
GROUP BY 1
HAVING orders_per_ad >= 2.5
ORDER BY 1;

패턴 3: 전체 프로모션 현황 통합

UNION ALL로 여러 캠페인 테이블을 세로 합치기

SELECT channel, date, ad_cost, 'BM' AS campaign_type FROM bm_mkt_promo
UNION ALL
SELECT channel, date, ad_cost, 'BR' AS campaign_type FROM br_mkt_promo
ORDER BY date;

패턴 4: 코호트 분석 (잔존율/이탈율)

특정 가입월(M+0) 기준으로 N개월 후 잔존 고객을 추적

WITH cohort AS (
    SELECT
        customer_id,
        MIN(EXTRACT(MONTH FROM first_order_date)) AS cohort_month
    FROM customers
    GROUP BY 1
)
SELECT
    c.cohort_month,
    EXTRACT(MONTH FROM o.order_date) - c.cohort_month AS months_after,
    COUNT(DISTINCT o.customer_id) AS retained_customers
FROM cohort c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY 1, 2
ORDER BY 1, 2;

시각화 팁: 코호트 결과를 스프레드시트 피벗 테이블로 전환한 뒤, 조건부 서식(색상 스케일)을 적용하면 잔존율 패턴이 한눈에 보인다.

패턴 5: 시간대별 주문 분포

SELECT
    EXTRACT(HOUR FROM order_datetime) AS hour,
    COUNT(*) AS order_cnt,
    SUM(order_amount) AS total_amount
FROM orders
GROUP BY 1
ORDER BY 1;

7. SQL 치트시트

쿼리 작성 순서

SELECT   (5) 조회할 컬럼 선택
FROM     (1) 대상 테이블 지정
WHERE    (2) 원본 데이터 필터링
GROUP BY (3) 그룹화
HAVING   (4) 집계 결과 필터링
ORDER BY (6) 정렬

괄호 안 숫자가 실행 순서. 작성 순서와 실행 순서가 다르다!

핵심 문법 한 장 정리

기능 문법 설명
조회 SELECT col FROM table 기본 데이터 조회
별칭 col AS alias 컬럼/테이블 이름 변경
필터 WHERE condition 원본 데이터 조건 필터
그룹화 GROUP BY col 컬럼 기준 묶음
집계 필터 HAVING agg() > n 집계 결과 조건 필터
정렬 ORDER BY col DESC 오름차순/내림차순
조건 분기 CASE WHEN ... THEN ... END IF와 유사한 조건 분류
형변환 CAST(col AS type) 데이터 타입 변경
문자열 추출 SUBSTR(col, start, len) 부분 문자열 추출
윈도우 LAG(col, n) OVER (ORDER BY ...) 이전/이후 행 참조
임시 테이블 WITH name AS (SELECT ...) 재사용 가능한 쿼리 블록
가로 연결 JOIN ... ON key 테이블 병합
세로 연결 UNION ALL 쿼리 결과 세로 합치기

WHERE 연산자 한 장 정리

연산자 문법 의미
= / != col = 'value' 같다 / 다르다
> >= < <= col >= 100 비교
AND / OR A AND B 그리고 / 또는
BETWEEN col BETWEEN A AND B A~B 범위
IN col IN ('a', 'b') 목록 내 일치
LIKE col LIKE '%keyword%' 패턴 매칭
IS NULL col IS NULL 값 없음
IS NOT NULL col IS NOT NULL 값 있음

더 많은 인사이트가 필요하신가요?

📚 너드보드 기술블로그 더보기 →

🚀 너드보드 7일 무료체험 해보기 →

🔥 7일 한정 특가: 99,000원29,000원

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment