データ分析SQLのコーディング規約
文字に関する規約
- 予約語/関数は、大文字にする。
- SQL自体は大文字小文字を区別しないが、予約語や関数を大文字にすることで可読性が向上する。
- JOINのASに単文字を使わない。(変数名も)
- 単文字だとテーブルの意味が分かりにくくなるため、明確な別名をつける。
- スネークケースで書く。
- 他のデータベースとの互換性のため、スネークケースを使用する。
- 接頭辞(prefix) / 接尾辞(suffix)をつける。
- 集計関数や時間単位などを接頭辞・接尾辞で明示する。
-
id
というカラム名は使わない。- 結合ミスを防ぐため、他のデータベースから読み込む際にカラム名を変更する。
体裁に関する規約
- 1行に1カラムにする。
- 複数カラムを1行に書くと分かりにくくなるため、1行1カラムを徹底する。
- インデントは2文字(スペース)にする。
- 分析クエリは横長になりがちなので、2スペースのインデントを使う。
- AND,ORは改行して先頭に配置する。
- 条件式が複数になる場合、改行して視認性を高める。
- SELECT単位でインデントを揃える。
- JOINが多い分析SQLでは、SELECT単位でインデントを揃えて階層を明確にする。
機能的規約
-
INNER JOIN
を使わない。- データ除外の危険性があるため、
LEFT JOIN
とWHERE句を使って丁寧に処理する。
- データ除外の危険性があるため、
- 一定の量が増えたらサブクエリを
WITH
句にする。- サブクエリが深くなりすぎないよう、3階層程度で
WITH
句を使う。
- サブクエリが深くなりすぎないよう、3階層程度で
- 集計時刻のカラムを作る。
- データマート作成時に
CURRENT_TIMESTAMP()
で集計時刻を記録する。
- データマート作成時に
- 集計期間には、ファンクション変数を使う。
- 日時変数は関数化し、変更に強いクエリにする。
例外
-
UNION
する場合は、上記の規約に従わなくてもよい。- 縦型から横型に変換する際など、可読性のために規約を変更してもよい。
まとめ
以上が、データ分析SQLのコーディング規約をまとめたものです。分析SQLは可読性とエラー防止が特に重要なので、これらの規約を意識してコーディングすることが大切です。ただし、状況に応じて柔軟に対応することも必要です。
データ分析SQLのコーディング規約
文字に関する規約
- 予約語/関数は、大文字にする。
- SQL自体は大文字小文字を区別しないが、予約語や関数を大文字にすることで可読性が向上する。
Bad:❌
select
max(created_at)
from
users
where
id = 1;
Good:✅
SELECT
MAX(created_at)
FROM
users
WHERE
id = 1;
- JOINのASに単文字を使わない。(変数名も)
- 単文字だとテーブルの意味が分かりにくくなるため、明確な別名をつける。
Bad:❌
SELECT
u.name,
p.product_name
FROM
users AS u
JOIN
purchases AS p ON u.id = p.user_id;
Good:✅
SELECT
users.name,
purchases.product_name
FROM
users
JOIN
purchases ON users.id = purchases.user_id;
- スネークケースで書く。
- 他のデータベースとの互換性のため、スネークケースを使用する。
Bad:❌
SELECT
userId,
createdAt
FROM
users;
Good:✅
SELECT
user_id,
created_at
FROM
users;
- 接頭辞(prefix) / 接尾辞(suffix)をつける。
- 集計関数や時間単位などを接頭辞・接尾辞で明示する。
Bad:❌
SELECT
COUNT(*) AS count,
SUM(price) AS sum
FROM
orders;
Good:✅
SELECT
COUNT(*) AS total_orders,
SUM(price) AS total_revenue
FROM
orders;
-
id
というカラム名は使わない。- 結合ミスを防ぐため、他のデータベースから読み込む際にカラム名を変更する。
Bad:❌
SELECT
users.id,
orders.i
FROM
users
JOIN
orders ON users.id = orders.user_id;
Good:✅
SELECT
users.user_id,
orders.order_id
FROM
users
JOIN
orders ON users.user_id = orders.user_id;
体裁に関する規約
- 1行に1カラムにする。
- 複数カラムを1行に書くと分かりにくくなるため、1行1カラムを徹底する。
Bad:❌
SELECT user_id, created_at, updated_at FROM users;
Good:✅
SELECT
user_id,
created_at,
updated_at
FROM
users;
- インデントは2文字(スペース)にする。
- 分析クエリは横長になりがちなので、2スペースのインデントを使う。
Bad:❌
SELECT
user_id,
COUNT(*) AS total_orders
FROM
orders
GROUP BY
user_id;
Good:✅
SELECT
user_id,
COUNT(*) AS total_orders
FROM
orders
GROUP BY
user_id;
- AND,ORは改行して先頭に配置する。
- 条件式が複数になる場合、改行して視認性を高める。
Bad:❌
SELECT *
FROM
users
WHERE
created_at >= '2022-01-01' AND created_at < '2023-01-01' AND status = 'active';
Good:✅
SELECT *
FROM
users
WHERE
created_at >= '2022-01-01'
AND created_at < '2023-01-01'
AND status = 'active';
- SELECT単位でインデントを揃える。
- JOINが多い分析SQLでは、SELECT単位でインデントを揃えて階層を明確にする。
Bad:❌
SELECT users.name, COUNT(orders.id) AS total_orders
FROM users
LEFT JOIN orders ON users.id = orders.user_id
WHERE users.created_at >= '2022-01-01'
GROUP BY users.id;
Good:✅
SELECT
users.name,
COUNT(orders.id) AS total_orders
FROM
users
LEFT JOIN
orders
ON users.id = orders.user_id
WHERE
users.created_at >= '2022-01-01'
GROUP BY
users.id;
機能的規約
-
INNER JOIN
を使わない。- データ除外の危険性があるため、
LEFT JOIN
とWHERE句を使って丁寧に処理する。
- データ除外の危険性があるため、
Bad:❌
SELECT
users.name,
COUNT(orders.id) AS total_orders
FROM
users
INNER JOIN
orders
ON users.id = orders.user_id
GROUP BY
users.id;
Good:✅
SELECT
users.name,
COUNT(orders.id) AS total_orders
FROM
users
LEFT JOIN
orders
ON users.id = orders.user_id
WHERE
orders.id IS NOT NULL
GROUP BY
users.id;
- 一定の量が増えたらサブクエリを
WITH
句にする。- サブクエリが深くなりすぎないよう、3階層程度で
WITH
句を使う。
- サブクエリが深くなりすぎないよう、3階層程度で
Bad:❌
SELECT
user_id,
total_orders
FROM
(
SELECT
user_id,
COUNT(*) AS total_orders
FROM
(
SELECT
user_id,
order_id
FROM
orders
WHERE
created_at >= '2022-01-01'
)
GROUP BY
user_id
);
Good:✅
WITH orders_filtered AS (
SELECT
user_id,
order_id
FROM
orders
WHERE
created_at >= '2022-01-01'
)
SELECT
user_id,
COUNT(*) AS total_orders
FROM
orders_filtered
GROUP BY
user_id;
- 集計時刻のカラムを作る。
- データマート作成時に
CURRENT_TIMESTAMP()
で集計時刻を記録する。
- データマート作成時に
Bad:❌
SELECT
user_id,
COUNT(*) AS total_orders
FROM
orders
GROUP BY
user_id;
Good:✅
SELECT
user_id,
COUNT(*) AS total_orders,
CURRENT_TIMESTAMP() AS aggregated_at
FROM
orders
GROUP BY
user_id;
- 集計期間には、ファンクション変数を使う。
- 日時変数は関数化し、変更に強いクエリにする。
Bad:❌
SELECT
user_id,
COUNT(*) AS total_orders
FROM
orders
WHERE
created_at >= '2022-01-01'
AND created_at < '2023-01-01'
GROUP BY
user_id;
Good:✅
CREATE TEMPORARY FUNCTION start_date() AS (DATE '2022-01-01');
CREATE TEMPORARY FUNCTION end_date() AS (DATE '2023-01-01');
SELECT
user_id,
COUNT(*) AS total_orders
FROM
orders
WHERE
created_at >= start_date()
AND created_at < end_date()
GROUP BY
user_id;
例外
-
UNION
する場合は、上記の規約に従わなくてもよい。- 縦型から横型に変換する際など、可読性のために規約を変更してもよい。
Example:
SELECT
user_id,
'order_count' AS metric,
COUNT(*) AS value
FROM
orders
GROUP BY
user_id
UNION ALL
SELECT
user_id,
'total_revenue' AS metric,
SUM(total_amount) AS value
FROM
orders
GROUP BY
user_id;
以上が、データ分析SQLのコーディング規約をまとめたものです。各項目についてGood/Badの例を追加し、規約の意図をより明確に示しました。これらの例を参考に、可読性と保守性の高いSQLを書くことを心がけましょう。