読めるSQLはオプションじゃない
未来の自分(とチームメイト)があなたを憎まないようにSQLクエリをフォーマットする方法。
クエリを引き継ぎます。1行です。400文字。複数のjoin、サブクエリ、CASE文がすべて一緒くたです。
理解するのを頑張ってください。
SQLのフォーマットは美学の問題ではありません。クエリがメンテナンス可能かどうかです。
密集したSQLの問題
SELECT u.id,u.name,o.total,p.name FROM users u JOIN orders o ON u.id=o.user_id JOIN products p ON o.product_id=p.id WHERE o.created_at>'2024-01-01' AND u.status='active' ORDER BY o.total DESC;
join条件はどこ?何がフィルタされている?各列はどのテーブルから?
これを午前2時にデバッグすることを想像してください。
同じクエリ、読める形
SELECT
u.id,
u.name,
o.total,
p.name
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN products p ON o.product_id = p.id
WHERE o.created_at > '2024-01-01'
AND u.status = 'active'
ORDER BY o.total DESC;
すべての句が独自の行。条件が整列。構造が見えます。
機能するフォーマットルール
句ごとに1行。 SELECT、FROM、WHERE、ORDER BYがそれぞれ独自の行を得ます。
列を別の行に。 長いSELECTリストがスキャン可能になります。
継続する条件をインデント。 複数のWHERE条件が整列。
キーワードは大文字。 SELECT、FROM、WHEREがテーブル名や列から目立ちます。
一貫した大文字小文字。 スタイルを選び、それを貫きましょう。
サブクエリのフォーマット
サブクエリは急速に乱雑になります。明確にインデントしましょう:
SELECT *
FROM orders
WHERE user_id IN (
SELECT id
FROM users
WHERE status = 'premium'
)
あるいはサブクエリが複雑な時はCTEを使いましょう:
WITH premium_users AS (
SELECT id
FROM users
WHERE status = 'premium'
)
SELECT *
FROM orders
WHERE user_id IN (SELECT id FROM premium_users)
CTEはネストされたサブクエリよりしばしば明確です。
JOINのフォーマット
常にjoinタイプを指定しましょう。JOIN だけは INNER JOIN ですが、明示的の方が良いです。
SELECT *
FROM orders o
INNER JOIN users u ON o.user_id = u.id
LEFT JOIN shipping s ON o.id = s.order_id
シンプルなjoinでは同じ行にjoin条件を。複雑な条件では次の行に分割。
パフォーマンスはどうなの?
フォーマットは実行に影響しません。データベースオプティマイザーは空白を気にしません。
でもフォーマットされたSQLの方が最適化しやすい。構造が見え、不要なjoinを識別し、欠落したインデックスを発見できます。
読めないSQLはパフォーマンス問題を隠します。
チーム標準
スタイルを選びましょう。ドキュメント化しましょう。自動フォーマッターで強制しましょう。
異なるスタイルが存在します。一部のチームはカンマを行の最初に置きます。一部はすべてを大文字に。一部はしません。
どのスタイルを選ぶかより、一貫性が重要です。
すべてのクエリは書かれるより多く読まれます。可読性のためにフォーマットしましょう。チームメイト——そして未来の自分——があなたに感謝します。