Help us understand the problem. What is going on with this article?

「分析SQLスタイルガイド」をかなり真面目に考えた

目次

コメント欄で「いや私はこう思う!」という意見をたくさんいただきました!ぜひそちらも御覧ください!(決して揶揄ではないです)

なぜSQLのスタイルガイドが重要なのか

SQLはプログラミング未経験者でもとっつきやすい言語と言われ、エンジニアや分析を本業としていない人でもSQLを使う機会が増えてきていると思います。

そんなSQLですが、こちらのブログでも指摘されている通り、一般的なスタイルガイドが定まっていません。スタイルガイドとはコードの書き方マナーようなもので、どこで改行するか、空白はいくつ入れるか、大文字を使うかなどの諸々を指します。

もしスタイルガイドが無いとこんな事が起こります

  • コードに一貫性が無いためミスを発見しづらくなる
  • クエリを書くたびに書き方を検討するのに頭を使う
  • コードを読みづらくレビュー効率が下がる
  • コードを解読するのが大変で再利用されず、組織の資産になりにくい

この記事の目的

この記事は自分のコーディングスタイルを他人に押し付けるものでも、自分以外のコーディングスタイルを批判するものでもありません。
あくまで、分析SQLスタイルガイドの一例を紹介するもので、どこかのチームがSQLのスタイルガイドを決める際、このブログが参考になればと思っております。

また、このコーディングガイドに対する反論もTwitter等でお待ちしております!

この記事の対象者

私は普段データ分析を職にしていて、エンジニアではありません。
この記事の対象者もSQLを使って分析をする分析者向けのものとなります。

よってシステムに組み込まれるようなSQLを想定しているわけではありませんが、共通点はあるはずですのでエンジニアの方の意見もお待ちしております。

分析SQLスタイルガイドの指針

スタイルガイドの紹介の前に、自分が大事にしている3つの指針をお伝えします。すべてのルールはこの指針に基づいて作られています、

手間を減らす

これはコーディングガイドを定める目的とも言いかえられる、最も大事にしている指針です。すべてのルールは手間を減らすためにあり、手間が増えて見栄えが美しくなるガイドは無意味です。
image.png

縦と横を意識する

私はSQLを書く際、縦と横のラインを強く意識しています。縦のラインはインデントによって作られ、横のラインは改行によって作られます。
image.png

役割ごとに分ける

オブジェクト指向とまでは言いませんが、役割の異なるクエリを同じ場所に書くことは人間の理解を妨げます。データの種類や処理の粒度が大きく異なるときはクエリを分けるべきです。
image.png

基本ルール

SQLを書く上で全体に影響する基本のルールです

予約語も全部小文字で書く

image.png
【メリット】コーディングが楽になる
いきなり好みが分かれるルールですみません。私はすべて小文字を強く押します。慣習で大文字にしている人が多いと思いますが、一度小文字で書いてみてください。楽さにびっくりしますよ。

見ずらいという人も居ますが、普通のエディターならシンタックスハイライトされますし、キレイにインデントしていれば容易に分かります。一番使う予約語はselect,from,and,orですがこれを毎回大文字にする苦労と、見分けやすくなるメリットどちらが大きいかは明らかだと思います。
いきなり熱が入りすぎました。ここからは落ち着いていきます。

左揃えで書く

image.png
【メリット】コーディングが楽になる
この記事を書くにあたり、ネット上の色々なコーディングルールを調べたところ、中央線に寄せて書く流派が一定数いることにかなり驚きました。

右揃えの場合、左端のインデント数がselectやfromで異なるので毎回打たないといけませんが、左揃えならタブを半角スペース4つに設定しておけば、1ステップでインデントできます。

インデントはタブを使わず半角スペース4つで統一

image.png
【メリット】クエリの書き換えが楽になる

多くの場合、タブと半角スペースは肉眼で見分けが付きません。混在していると、クエリを書き換えるときに「....っおいタブかい!」となります。タブはエディターによって見え方が半角スペース4つ分だったり8つ分だったりするので、半角スペースに統一します。

半角スペースの数は4が視認性が良いのでそうしていますが、正直2でもいいと思ってます。戦う意志はありません。4つだと横に長くなりすぎると言うのであればそれはクエリに問題があると思います

カンマ(,)/and/orは先頭に置く

image.png
【メリット】クエリのミスが減る
後ろよりも先頭にある方がカンマ/and/orの視認性がよく、入力忘れが減ります
先頭カンマが違和感あるという人が多いですが、個人的にはandが先頭にあるのにカンマが文末にあるチグハグ感の方が違和感があるほか、列の増減作業が楽というメリットもあります。
私はカンマ文頭派ですがカンマ文末派のほうが多いようです!

andやorを単独行に置く人も居ますが、先頭に置くことでwhere句の行数=条件の数になるのでクエリを読み解きやすいです。

1つのselectごとにクエリの説明を書く

【メリット】クエリを読みやすくなる

with句やサブクエリによって、ひとつのクエリの中に複数のselectが入ることがあります。最低限その単位でクエリの説明を書くことは、小さな苦労ですが読む側にとってはとてもありがたいものです。
image.png

命名規則

asで列名やテーブル名を決める際の命名規則を定めます。

基本ルール

すべて小文字で書き、アンダーバーでつなぐ(snake case
image.png

略語は使わない
image.png

列名

列の内容によって接尾辞を定めておくことで、統一性があって見やすく毎回考える手間が省ける

接尾辞 利用タイミング
_id primary keyなどのidカラム
_flag フラグなどの何らかのステータス
_date 日付に関するカラム
_name 何かの名前を意味するカラム
_ratio 比率を表すカラム
_sum sum()の取得カラム
_count count()の取得カラム
_min min()の取得カラム
_max max()の取得カラム

テーブル名

分析においてテーブル名は柔軟に決めるべきで、決めすぎるべきではないと思っています。ここで示す接尾時はルールではなく考え方の参考としてください。

接尾辞 利用タイミング
_act 行動単位のテーブル
_user ユーザユニークのテーブル
_day 日別のテーブル
_month 月別のテーブル

インデントルール

1段目から3段目にかけて徐々に処理の粒度を細かくしていく。同じ階層に異なる粒度の処理を書かない。
【メリット】コードを構造的に読むことができ、理解しやすい

1段目は処理の大区分を示す句だけ(select,from,groupby,with,orderby)

一段目は大区分にすることで、コード全体のどこに何が書いてあるかがすぐに分かる。
image.png

2段目は処理関数、列名、テーブル名を並べる(列名、テーブル名、case whenのcase)

2段目を見ることで処理の概要とインプットとアウトプットが理解できる。
image.png

3段目は処理の補足を記載する(joinのon、case whenのwhen)

3段目を見ることで、より詳細な処理の内容を詳しく知ることができる
image.png

別名ルール

SQLの別名は、うまく使えば読みやすくなり、下手に使うと読みづらくもなります。

テーブルの別名は先頭の文字を使う。重複する場合は連番を振る。

image.png
別名をa,b,cやt1,t2と使う人は多く存在しますが、考える手間を省く以外にはあまり意味がありません。参照するテーブル名の先頭の文字使い、重複してしまう場合は連番を振ることで機械的に別名を決められ、手間を増やさずわかりやすくなります。

テーブルを複数結合したクエリでカラムを指定するときはテーブルの別名を明示する

image.png
テーブルを複数結合しているクエリでこれを行わないと、クエリを読むだけではこのカラムはどのテーブルのカラムなのか分かりません。テーブル定義書を読んだり実際にテーブルの中身をselectして調べなければいけない手間が増えます。

joinルール

SQLのミスで最も多いのがjoinです。ここではミスを減らすスタイルガイドを紹介します。

right joinは絶対に使わない

image.png
right joinと全く同じことはleft joinで実現できます。両者が混在すると読む人に大きな負担を与えます。人間は左側を起点に考える傾向があり、それに逆らうメリットがない以上right joinを使う理由が全くありません。

left joinを基本とし、絞り込む意図があるときのみinner joinを使う

image.png
inner joinは意図せず行を削ってしまい、それに気づきにくいという欠点がある。例えば購買ログデータと商品マスタをでinner joinで結合する際、マスタに不備があったとしても、出力からその行そのものが無くなるので不備に気づきにくい。

「逐一データの行数をチェックすれば問題ない」という意見はもっともですが、そもそもそのリスクは減らすべきです。

ちなみに、筆者のleft joinとinner joinの利用頻度はだいたい9:1程度です。

クエリ分割ルール

複雑なクエリは読む側にも負担を与えます。それを少しでも軽減するルールを紹介します。

サブクエリではなくwith句を使う

image.png
with句を使うことによって、クエリを上から下に読むことができます。サブクエリにしてしまうと、クエリの構造を理解するところからはじめる必要があり間違えずに読むことに脳の神経を取られます。

似た処理を何回もする場合は中間テーブルを作る

データ分析でSQLを書く際、一度やって終わりではなく途中から分岐して試行錯誤することは少なくありません。そのようなときに中間テーブルを作っておけば、処理時間の短縮につながるだけでなく、別の人がクエリを読む際に量が減る効果があります。

最後に

ここに書いたスタイルガイドは理想論ではなく、実務で実現可能なガイドだと思っています。また、あくまでガイドであり、状況によってはガイドに従うべきでないときもあります。サクッと確認するだけの残らないクエリは私もここのガイドをガッツリ無視して書いています。

ぜひ、「今のやり方に慣れてるから…」「大文字で書く癖が付いてるから…」と尻込みせずこのスタイルを試してみて、感想をお聞かせください!

Twitterもやっているので、DMやリプで意見いただけると嬉しいです!

参考

kai_data
主にTwitterで活動しているデータサイエンティストです。 データ活用の現場で日々学んだことを図解まとめてTwitterに投稿しています。
https://twitter.com/kai_data
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away