# 가독성 있는 쿼리 작성하기

SQL 쿼리를 작성하다보면, 사람들마다 자신만의 스타일로 쿼리를 작성하곤 합니다. 처음엔 데이터를 추출하는 시간이 중요하기 때문에, 쿼리를 자유롭게 작성합니다. 그러다 팀 규모가 커지고, 많은 사람들이 쿼리를 작성하면 다른 사람의 쿼리를 공유받는 경우가 생깁니다. 다른 사람의 쿼리가 가독성 있게 작성되었다면 읽을 때 문제가 되지 않지만, 가독성이 없는 경우라면 쿼리를 읽는데 시간이 더 소요되게 됩니다.

  • 예시로 SELECT 문에서 컬럼을 선택할 때, 쉼표를 뒤에 두느냐(Trailing Comma) vs 앞에 두느냐(Leading Comma)
    • 이런 내용으로 매번 수정 요청하는 것은 조직 차원에서 시간이 아까울 수 있습니다.

이런 경우를 방지하고자 회사에서 SQL 스타일 가이드를 만들고 운영합니다. 혹은 Linter 등을 설정해 균일된 형식을 사용하게 만듭니다. 이 글에선 SQL 스타일 가이드에 대해서만 다룹니다.



# SQL 스타일 가이드의 목적

결국 목적은 단 하나 : SQL 쿼리를 쉽게 작성하고, 읽기 쉽게 유지하기 위해. 다른 사람들이 읽어도 빠르게 이해할 수 있도록 만듭니다.

저는 SQL을 명시적으로 작성하면 쿼리가 더 쉬워집니다라고 생각합니다.



# 다양한 스타일 가이드

SQL 스타일 가이드는 다른 프로그래밍 언어와 다르게 엄격하게 "이렇게 모두 지켜야 합니다!"라는 것은 없습니다. 조직에서 합의하는 과정이 필요합니다.

웹에 공개되어 있는 SQL 스타일 가이드를 공유드립니다



# 예약어

SELECT, FROM 등은 저희가 따로 정의하지 않은 예약어입니다. 이런 예약어는 모두 대문자로 작성해주세요.

함수도 대문자로 작성합니다.

# Good
SELECT
  col1,
  col2
FROM 
  Table
WHERE 
  condition
# Bad
select
  col1,
  col2
from 
  Table
where 
  condition


# 변수 이름

변수 이름은 소문자와 언더바를 사용하는 snake_case를 사용합니다. 예 : first_name

WITH 문의 CTE도 마찬가지로 snake_case를 사용합니다.

# Good
WITH base AS (
  SELECT
    first_name,
    second_name
  FROM 
    Table
)

SELECT
  first_name,
  CONCAT(first_name, second_name) AS full_name
FROM 
  base


# 명시적인 표현

암묵적(Implicit)인 표현보단 명시적으로 확실한(Explicit) 표현을 선호합니다.


# AS

변수나 테이블 이름에 별칭을 지정할 경우 AS를 생략할 수 있지만, AS를 작성해주시는 것이 명시적으로 읽기 좋습니다.

# Good
WITH base AS (
  SELECT
    first_name,
    second_name
  FROM 
    Table
)

SELECT
  first_name,
  CONCAT(first_name, second_name) AS full_name
FROM 
  base
# Bad
WITH base AS (
  SELECT
    first_name,
    second_name
  FROM 
    Table
)

SELECT
  first_name,
  CONCAT(first_name, second_name) full_name
FROM 
  base

# GROUP BY, ORDER BY 1

GROUP BYORDER BY 뒤에 컬럼 이름을 작성하지 않고, 1, 2, 3 등을 사용할 수 있습니다. 여기서 1의 의미는 첫번째 SELECT한 컬럼을 의미합니다.

빠르게 작성할 땐 유용할 수 있지만, 명시적이지 않습니다. 명시적으로 작성해주세요.

# Bad
WITH base AS (
  SELECT
    first_name,
    second_name
  FROM 
    Table
)

SELECT
  first_name,
  COUNT(first_name) AS first_name_count
FROM 
  base
GROUP BY 
  1


# 코드 블럭

쿼리문의 한 줄마다 하나의 컬럼만 존재하는 것이 좋습니다. 다만 요소가 하나인 경우엔 한 줄에 작성해도 어느정도 받아들일 수 있습니다.

# Good
WITH base AS (
  SELECT
    first_name,
    second_name
  FROM 
    Table
  WHERE
    first_name = "Byeon"
    AND user_id = 123
)

SELECT
  first_name,
  CONCAT(first_name, second_name) AS full_name
FROM 
  base
# Acceptable
WITH base AS (
  SELECT
    first_name,
    second_name
  FROM Table
  WHERE
    first_name = "Byeon"
    AND user_id = 123
)

SELECT
  first_name,
  CONCAT(first_name, second_name) AS full_name
FROM base


# 콤마

BigQuery는 컬럼의 마지막에 콤마가 있어도 정상적으로 실행됩니다(예전엔 마지막에 콤마가 에러를 발생했지만, 수정되었습니다)

  • 콤마를 앞에 두는 경우 : Leading Comma
    • 이런 경우 주석 처리가 한번에 된다는 장점이 있습니다.
    • 빅쿼리는 맨 뒤에 콤마가 있어도 정상적으로 쿼리가 실행됩니다
  • 콤마를 뒤에 두는 경우 : Trailing Comma
SELECT
  col1,
  col2,
FROM 
  Table
SELECT
  col1
  , col2
  # , col3
FROM 
  Table


# 들여쓰기(Indent)

들여쓰기(Indent)는 탭 한번(띄어쓰기 기준 2번)을 사용합니다.

쿼리문이 중첩되는 경우, 전체적으로 한번 들여써줍니다(아래 예시에서 base와 favorite_food쪽)

WITH base AS (
  SELECT
    id,
    first_name,
    second_name
  FROM user
), favorite_food AS (
  SELECT
    user_id,
    food_id,
    food_name
  FROM food
)

SELECT
  base.id AS user_id,
  food.food_id AS food_id,
  food.food_name AS food_name
FROM 
  base 
LEFT JOIN favorite_food AS food
ON base.id = favorite_food.user_id


# WITH

WITH 문을 사용하면 가독성 있는 쿼리를 작성할 수 있습니다.

WITH 문에 대한 내용은 해당 가이드북의 BigQuery 중급 - WITH를 참고해주세요