# 가독성 있는 쿼리 작성하기
SQL 쿼리를 작성하다보면, 사람들마다 자신만의 스타일로 쿼리를 작성하곤 합니다. 처음엔 데이터를 추출하는 시간이 중요하기 때문에, 쿼리를 자유롭게 작성합니다. 그러다 팀 규모가 커지고, 많은 사람들이 쿼리를 작성하면 다른 사람의 쿼리를 공유받는 경우가 생깁니다. 다른 사람의 쿼리가 가독성 있게 작성되었다면 읽을 때 문제가 되지 않지만, 가독성이 없는 경우라면 쿼리를 읽는데 시간이 더 소요되게 됩니다.
- 예시로 SELECT 문에서 컬럼을 선택할 때, 쉼표를 뒤에 두느냐(Trailing Comma) vs 앞에 두느냐(Leading Comma)
- 이런 내용으로 매번 수정 요청하는 것은 조직 차원에서 시간이 아까울 수 있습니다.
이런 경우를 방지하고자 회사에서 SQL 스타일 가이드를 만들고 운영합니다. 혹은 Linter 등을 설정해 균일된 형식을 사용하게 만듭니다. 이 글에선 SQL 스타일 가이드에 대해서만 다룹니다.
# SQL 스타일 가이드의 목적
결국 목적은 단 하나 : SQL 쿼리를 쉽게 작성하고, 읽기 쉽게 유지하기 위해
. 다른 사람들이 읽어도 빠르게 이해할 수 있도록 만듭니다.
저는 SQL을 명시적으로 작성하면 쿼리가 더 쉬워집니다
라고 생각합니다.
# 다양한 스타일 가이드
SQL 스타일 가이드는 다른 프로그래밍 언어와 다르게 엄격하게 "이렇게 모두 지켜야 합니다!"라는 것은 없습니다. 조직에서 합의하는 과정이 필요합니다.
웹에 공개되어 있는 SQL 스타일 가이드를 공유드립니다
- Mozilla(Firefox)의 SQL Style Guide (opens new window) : 개인적으로 이 가이드를 추천합니다
- Gitlab의 SQL Style Guide (opens new window)
- Simon Holywell의 SQL Style Guide (opens new window) : 이 문서를 토대로 대부분 스타일 가이드가 만들어짐
- Lumoslabs의 SQL Style Guide (opens new window)
- Mattm의 SQL Style Guide (opens new window)
- SQL Best Practices and Style Guide (opens new window)
- Kickstart의 SQL Style Guide (opens new window)
# 예약어
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 BY
와 ORDER 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를 참고해주세요