[SQL] 11. 쿼리 가독성(WITH), 데이터 결과 검증

2025. 2. 23. 18:05·SQL/BigQuery



1. 가독성을 높이는 SQL 쿼리 가이드

  • 쿼리를 가독성 있게 잘 써두면 동료들에게 설명할 시간을 줄일 수 있음
    • +쿼리를 단순화하거나 쪼갤 줄 알면 실수를 줄일 수 있음
  • 쿼리를 변경/수정할 경우에도, 어떤 부분이 바뀐 건지 파악하기 쉬워야 함
  • 그래서 가독성을 챙기기 위한 가이드들이 존재함
    • SQL 스타일 가이드 : https://www.sqlstyle.guide/
    • Mozilla(Firefox) 스타일 가이드 : https://docs.telemetry.mozilla.org/concepts/sql_style.html
 

SQL Style Guide - Mozilla Data Documentation

From Pep8: A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is the most important. However, know when to be inconsistent -- sometim

docs.telemetry.mozilla.org

가이드는 조직마다 다를 수 있는데, 우리는 Firefox 가이드의 대표적인 내용 몇 개만 살펴보자!

 

 

1. 예약어는 대문자로 작성

  • 예약어 : SELECT, FROM, WHERE, AS 등 각종 문법적인 함수

2. 컬럼 이름은 snake_case로 작성

  • 모든 단어는 소문자로 시작하고, 단어와 단어 사이는 "_"(underscore)로 연결
  • cf) 회사의 지침이 CamelCase이면 그걸 사용. 일관성이 중요!

3. 별칭(Alias)은 명시적인 이름을 사용

  • AS a, AS b 등 한 번 더 생각해야 하는 이름이 아닌, 명시적인 이름(ex. kor_name)을 사용
  • JOIN할 때 테이블 이름도 웬만하면 명시적으로 하는 걸 권장

4. 왼쪽 정렬을 기준으로 작성

  • 기본적으로 왼쪽 정렬해서 작성

5. 예약어, 컬럼은 한 줄에 하나씩

  • 바로 주석 처리(ctrl+/)하기 편하도록 한 줄에 하나씩만 작성하는 걸 권장함

6. 쉼표는 컬럼 바로 뒤에

  • 의견 갈릴 수 있는 부분! (예전에는 중간에 컬럼 하나 없애도 그대로 쓸 수 있도록 컬럼 앞에 쓰기도 했었음)
  • 근데 BigQuery는 마지막 쉼표를 무시해주기 때문에 뒤에 써도 무방함!

 

2. WITH문과 파티션

WITH ~ AS

  • 쿼리 작성하다보면 생기는 문제 : 
    • 서브쿼리로 감싸는 경우가 많은데, 그게 많아지다보면 가독성이 매우 떨어짐 (제일 안쪽 서브쿼리부터 읽어야하니까..)
    • 쿼리 중 반복되는 부분이 많아질 경우, 수정할 때 어떤 부분은 놓치게 될 수 있음
  • 이런 문제를 해결하고, 가독성 확보를 도와주는 것이 바로 WITH문!
    • 특정 쿼리 부분 자체를 별칭으로 지정해서 재사용하는 방법!
    • CTE(Common Table Expression)이라고 표현하며, SELECT 구문에 이름을 정해주는 것
    • 쉼표로 연결해서 여러 쿼리를 한 번에 지정할 수도 있음

 

👨‍🏫Tips
- 보통 가장 기본이 되는 테이블 형태를 WITH base AS ~ 로 베이스 테이블 만들고 그걸로 다른 쿼리 쓰는 편
- 혹은 재사용하고 싶은 부분을 Table 또는 View로 따로 저장을 할 수도 있긴 함. (아래 'BigQuery 실습' 부분 참고)

 

 

PARTITION

  • 파티션(Partition) : 하나의 큰 테이블을 논리적으로 여러 개의 작은 테이블로 분할해서 저장하는 방법
    • ex) 테이블에는 수많은 데이터가 매일 추가될 수 있음 ➔ 특정 시기에 들어온 데이터를 찾고 싶은데 잘 모르면 탐색하면서 비용 너무 많이 쓰게 됨... ➔ 이런 경우, 애초에 일자별로 정리하면 됨! = 이게 바로 파티션!
  • 보통은 DATE 데이터를 기준으로 많이 사용함 (다른 타입도 가능하긴 함)
    • ex) 파티션으로 저장했던 battle 테이블을 '새 탭에서 열기' 해보면, battle_datetime 기준으로 파티션이 자동 적용되어 있는 것을 볼 수 있음
    • 여기서 날짜를 원하는 대로 조정하면서 쓸 수도 있는 것! 데이터 더 많이 필요할 때 날짜 범위 늘린다든가...

 

👍Partition 장점

  • 쿼리 성능 향상: 전체 데이터 다 스캔하는 것보다 파티션 설정한 곳만 스캔하는 게 더 빠름
  • 비용 절감: 파티션 설정한 곳만 스캔하니까 비용 줄일 수 있음 (BigQuery는 쿼리 용량에 비례해서 과금함)
  • 데이터 관리 용이: 특정 일자의 데이터를 모두 변경/삭제해야 할 경우 파티션에만 적용할 수 있음

 

BigQuery 실습

  • WITH문으로 쿼리의 일부분을 재사용 가능 (단, WITH문만 있으면 실행 안 됨! 그 밑에 SELECT문으로 뭔가 해줘야 함)

  • 또, 아예 쿼리 결과 자체를 테이블(BigQuery Table)로 저장 가능 (단, 저장 비용 발생!)

  • 또는 뷰(View)로 저장 가능 (단, 속도가 상대적으로 느림.)

 

3. 데이터 결과 검증⭐

데이터 결과 검증의 필요성

  • 👨‍🏫예시 상황 : 갑자기 30분 만에 데이터 추출해서 보고해야하는 상황 발생 - 제출 후에 혹시나 확인해보니 급하게 작업하느라 오류가 있었음 - 이런 실수를 데이터 직무에서 한번쯤 겪게 됨 ➔ 어떻게 이런 실수를 예방할 수 있을까?
  • 결과 검증을 잘 하기 위한 마인드셋 : 실수는 누구나 할 수 있다! 같은 실수를 반복하지 않도록 시스템을 구축하는 게 중요! (회고도 필수!)

데이터 결과 검증 방법

  • 의미 : SQL 쿼리 실행해서 얻은 결과가 예상과 일치하는지 확인하는 과정 ➔ 분석의 정확성 & 신뢰성 확보!
  • 구체적인 흐름
    1. 문제를 구체적으로 정의하기, 요청사항도 확인하기 (ex. 원하시는 결과가 이런 게 맞나요?)
    2. 데이터의 Input과 예상되는 Output 작성해보기 (⭐구체적으로! 손으로 그리거나 엑셀에 적어봐야 함!)
      • Input - Output 사이에 중간 결과가 필요할 경우 그것도 순차적으로 생각하기
    3. 쿼리 작성하기 (가독성 챙겨서!)
    4. 실행 결과와 (2)에서 예상했던 것과 비교하기
      • 차이가 있다면 : (3)으로 돌아가 다시 쿼리 작성 (근데도 해결 안 되면 (1)로 돌아가서 문제 정의 다시 점검)
      • 차이가 없다면 : 끝 !
  • 자주 활용하는 쿼리
    • `COUNT(*)` : 행(row) 개수를 확인. '예상 결과와 행 개수가 맞는지?'
    • `NOT NULL` : 특정 컬럼에 NULL있는지 확인. '필수 컬럼이 비어있지는 않은지?'
    • `DISTINCT` : 데이터의 고유값을 출력해 중복 여부 확인. 'COUNT()와 COUNT(DISTINCT())가 동일한지?'
    • `IF` / `CASE WHEN` : 조건문을 사용해 의도한 결과와 같으면 True를 출력하도록.
👨‍🏫실제 결과 검증 예시

1) 특정 user_id 하나를 콕 집어서 확인해보고, 전체로 적용
- 1명의 데이터 확인 (ex. WHERE user_id = 402)
- Raw 데이터에서 직접 눈으로 계산해서 결과 예상 (ex. count하면 이 행은 30이라고 나오겠네)
- (WHERE 걸었던) 1명 데이터의 예상 결과와 (WHERE 없앤) 전체 쿼리 결과가 동일한지 확인
- 혹시 모르니, 다른 user_id 3~4건 더 추가해서 확인 (여러 케이스가 존재할 수 있으니까)
- 3~4개에서 동일한 결과가 나오면 WHERE 조건을 삭제

2) 샘플 데이터로 쿼리 맞는지 확인해보기
- WITH 문으로 샘플 데이터를 생성 (UNION ALL 사용해서 수동으로 데이터 생성)
- 결과를 예상하고 쿼리 작성
   (=복잡한 데이터에서 하기 전에, 간단한 데이터로 쿼리 자체가 올바른지 확인할 때 사용)
출처 : 카일스쿨, 초보자를 위한 BigQuery(SQL) 입문

 

데이터 결과 검증 연습

👨‍🏫여러분은 포켓몬 트레이너들의 배틀 성적을 분석하는 작업을 맡게 되었습니다. 각 트레이너의 배틀 승리 비율을 계산해야 하며, 배틀에 참여한 횟수가 9회 이상인 경우만 계산합니다. 데이터 결과 검증을 시도하면서 문제를 풀어보세요

 

❎내가 생각한 풀이

1) trainer_id = 13인 행('Goh')으로 일단 감 잡기

직접 user 하나 택해서 검증하는 논리는 맞음

2) battle 테이블과 trainer 테이블을 player1_id를 Key로 JOIN?? (여기서 막힘)

 

✅강사님 풀이

1) 7번 트레이너(trainer_id = 7인 행)를 샘플로 잡고 승리 비율 직접 계산 여기까진 맞음

  •  참여 횟수 9회 / 승리 횟수 5회 ⇒ 승리 비율 = 0.5555...

2) player1_id, player2_id로 쪼개져 있어서 그냥 사용 불가 ➔ 테이블 전처리 필요⭐

  • UNION ALL 써서 두 컬럼을 trainer_id라는 한 컬럼으로 합쳐버림! (즉, 배틀 1회의 정보가 2행에 나뉘어 기록됨)
  • 전처리한 테이블을 WITH문 사용해서 battle_basic이라는 테이블로 재사용! 

 

3) 전처리한 battle_basic 테이블에서, 7번 트레이너의 '총 배틀 횟수' 구해봄

  • 이때, 결과 검증(중복 있는지 점검)을 위해 COUNT()와 COUNT(DISTINCT()) 둘 다 출력해봄
  • 둘 다 똑같이 9로 나옴 = 1단계에서 예상한 결과와 동일함 🆗

 

4) CASE WHEN을 써서 배틀 결과를 win / lose / draw로 표시하는 컬럼 "battle_result"을 추가함

  • 그리고 battle_result 컬럼에서 "win" 개수를 세면 승리 횟수를 구할 수 있음! 

 

5) battle_result 컬럼이 추가된 테이블을 다시 battle_with_result 테이블로 지정 (=WITH문 사용)

 

6) battle_with_result 테이블에서 COUNT로 승리 횟수, 총 배틀 횟수 계산 ➔ 승리 비율 계산!

  • battle_with_result 테이블 자체에 WHERE 조건 걸려있어서 아직은 7번 트레이너에 대한 결과만 나옴
       = 우리가 1단계에서 예상했던 결과와 동일함 🆗

7) 이제 battle_with_result 테이블에서 WHERE trainer_id=7 조건 해제하면, 전체 트레이너에 대해 결과가 나옴!!

  • 실제로는, 7번 트레이너 말고 다른 번호로 바꿔서 몇 개 더 검증해보는 것을 추천!

8) 마지막으로 HAVING으로 '배틀 참여 횟수 9회 이상' 조건까지 추가해주면, 최종 결과 완성!!✅

  • ⚠️COUNT로 집계한 컬럼에 대한 조건이니까 WHERE 아니고 HAVING 사용;;
  • 검증 흐름을 정리하자면 : 전체 데이터 파악 ➔ 특정 user_id 선택 ➔ 승률 직접 COUNT해서 결과 예상 ➔ 쿼리 작성 ➔ 실제와 비교 ➔ 맞다면 특정 user_id 조건 제외

 

전체 코드는 더보기 클릭

더보기
WITH battle_basic AS (  
  SELECT  
    id AS battle_id,  
    player1_id AS trainer_id,  
    winner_id  
  FROM `basic.battle`  
  UNION ALL
  SELECT  
    id AS battle_id,  
    player2_id AS trainer_id,  
    winner_id  
  FROM `basic.battle` 
), battle_with_result AS( --battle_with_result로 추가 테이블 지정
  SELECT
    *,  
    CASE  --winner_id 기준으로
      WHEN trainer_id = winner_id THEN "WIN" --trainer_id와 같으면 승리
      WHEN winner_id IS NULL THEN "DRAW" --NULL이면 무승부
      ELSE "LOSE" --trainer_id와 다르면 패배
    END AS battle_result -- 그걸 하나의 컬럼으로 저장
  FROM battle_basic  
  -- WHERE trainer_id = 7 (이제 주석 처리해서 전체 트레이너로 확장!)
) 

SELECT  
  trainer_id,  
  COUNTIF(battle_result = "WIN") AS win_count, --승리 횟수
  COUNT(battle_id) AS total_battle_count, --총 배틀 횟수
  COUNTIF(battle_result = "WIN") / COUNT(DISTINCT battle_id) AS win_ratio --승리 비율
FROM battle_with_result
GROUP BY  
  trainer_id --트레이너마다 계산
HAVING
  total_battle_count>=9; --전체 배틀 수 9 이상으로 추가 조건까지 걸면 완성!
  
--❎내 풀이 과정 --
SELECT -- 13번 트레이너의 배틀 횟수 = 10
  -- id,
  -- player1_id,
  -- player2_id,
  -- winner_id,
  COUNT(id) AS battle_cnt
FROM `bigquery-studying.basic.battle`
WHERE
  player1_id=13 OR player2_id=13;

SELECT -- 13번 트레이너의 승리 횟수 = 2
  -- id,
  -- player1_id,
  -- player2_id,
  -- winner_id,
  COUNT(id) AS battle_win_cnt
FROM `bigquery-studying.basic.battle`
WHERE
  winner_id=13

 

 


🙏References

  • 카일스쿨 님의 인프런 강의 (https://www.inflearn.com/course/%EC%B4%88%EB%B3%B4%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%B9%85%EC%BF%BC%EB%A6%AC-sql-%EC%9E%85%EB%AC%B8/dashboard) 를 듣고 정리한 내용입니다.

'SQL > BigQuery' 카테고리의 다른 글

[SQL] 핵심 정리 노트  (0) 2025.03.06
[SQL] 12. 연습문제 풀이  (0) 2025.02.28
[SQL] 10. 데이터 연결 (JOIN)  (2) 2025.02.21
[SQL] 9. 조건문 (CASE WHEN, IF)  (0) 2025.02.15
[SQL] 8. 다양한 데이터 타입 (날짜 및 시간)  (0) 2025.02.13
'SQL/BigQuery' 카테고리의 다른 글
  • [SQL] 핵심 정리 노트
  • [SQL] 12. 연습문제 풀이
  • [SQL] 10. 데이터 연결 (JOIN)
  • [SQL] 9. 조건문 (CASE WHEN, IF)
simon919
simon919
개인적으로 공부한 내용을 기록하고 나누는 블로그입니다. 데이터 분석, 인공지능에 관한 내용을 주로 다룹니다.
  • simon919
    문과생의 AI 생존기
    simon919
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • ML & DL (38)
        • 머신러닝 기초 (23)
        • 딥러닝 기초 (6)
        • 데이터마이닝 (9)
      • Data structure & Algorithm (1)
      • SQL (24)
        • BigQuery (13)
        • MySQL (8)
        • SQLD 자격증 (3)
      • Statistics (12)
        • 교육 연구를 위한 통계 (10)
        • Linear Algebra (0)
        • AB Test (2)
      • Python (17)
        • Pandas (16)
        • Matplotlib (0)
        • Numpy (0)
        • Web Crawling (1)
      • Projects (0)
      • Etc. (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 글자가 깨지면 새로고침 해주세요 :)
  • 인기 글

  • 태그

    SQL
    Functional API
    SQL코딩테스트
    데이터마이닝
    SQLD 1과목
    Conv2d
    google cloud
    티스토리 스킨
    혼공머신
    BigQuery
    리트코드
    HELLO 스킨
    최우수혼공족
    블로그 스킨
    통계학 기초
    mysql
    SQLD
    pandas
    특성맵 시각화
    kmooc
    Bayesian Optimization
    Xai
    ml기초
    해커랭크
    pytorch
    MaxPooling2D
    혼공학습단
    교육통계
    kmeans
    SQL문제풀이
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
simon919
[SQL] 11. 쿼리 가독성(WITH), 데이터 결과 검증
상단으로

티스토리툴바