[SQL]インデントを正しく効果的に使おう

# インデントを正しく効果的に使おう
インデントを制すものは、コーディングを制す。
ごめんなさい、嘘です。
でも、初心者こそ、インデントきれいにしてほしい。

## インデントってなんのためにあるの?
インデントというのは、文章でいう改行的な意味合いで使っていただくとよいです。読みやすいし、理解しやすいし、メンテしやすい。
一体どういう風にやるのかといえば、個人的には「インデントで階層構造を作る」というのが一番しっくりきてます。
pythonとかいい例ですね。作った人天才ですね。

## 演習
SQLでちょっとやってみましょう。
使用しているテーブルの定義は、下の方にちょろっと書いておきますが読まなくても内容はわかるかと思います。(というより読まない方が効果を実感できるかも)

### 悪い例
ちょっと悪い例を書いてみましょう。

```SQL
select
salses.id, sales.name, companies.name, sales_contact.mail
from
sales
left outer join sales_contact on  sales.id = sales_contact.sales_id
left outer join sales_belonging on  sales.id = sales_belonging.sales_id
left outer join companies on  sales_belonging.company_id = companies.id
where
(sales.age > 20
or
sales.age < 40)
and sales_contact.mail is not null
```

いかがでしょうか・・・。
一発で解読できますか?
できるのであれば、このままページをそっ閉じ。

#### なにが問題?
- 構造が見えない
  - SELECT句, FROM句, WHERE句
  - FROM句内のテーブル構造
  - AND, ORの条件

### では、いったんちょっとインデントしてみる
「SELECT句, FROM句, WHERE句」をわかりやすくしてみる。

```SQL
select
  salses.id, sales.name, companies.name, sales_contact.mail
from
  sales
  left outer join sales_contact on  sales.id = sales_contact.sales_id
  left outer join sales_belonging on  sales.id = sales_belonging.sales_id
  left outer join companies on  sales_belonging.company_id = companies.id
where
  (sales.age > 20
  or
  sales.age < 40)
  and sales_contact.mail is not null
```
これだけでも、気持ちだいぶ違う。

### WHERE句にもインデントを
```
( sales.age > 20 OR sales.age < 40 ) and sales_contact.mail is not null
```
なので、まぁこのくらいなら一行でもいいんだけれど、ちょっとやってみる。

```SQL
where
  (
    sales.age > 20
    or sales.age < 40
  )
  and sales_contact.mail is not null
```

下でもよさそう。ここは、所属の好みやルールに沿って変えればいいかと。

```
where
  ( sales.age > 20 or sales.age < 40 )
  and sales_contact.mail is not null
```

私が真ん中の改行するやり方にこだわっているのは、条件をコメントアウトするときなどに便利だからです。

### (インデントから逸れて)改行を足してあげる
SELECT句の中に何が入っているのか分かりづらい・・・。
FROM句において、なにが繋がっているのか所見ではちょっと分かりづらい。(個人的に)
ということで改行します。

```SQL
select
  salses.id
  , sales.name
  , companies.name
  , sales_contact.mail
from
  sales
  left outer join
    sales_contact
    on  sales.id = sales_contact.sales_id
  left outer join
    sales_belonging
    on  sales.id = sales_belonging.sales_id
  left outer join
    companies
    on  sales_belonging.company_id = companies.id
where
  (sales.age > 20
  or
  sales.age < 40)
  and sales_contact.mail is not null
```

FROM句のjoinは、この形はだめだよ!という方もいらっしゃると思うので、是非ご意見を伺いたいです。
個人的には、どのテーブルをjoinさせて、どのカラムを参照しているのかを目で追う労力を少なくしたいのでこういう形にしています。
全員がテーブル構造を頭にいれた状態では不要かな、とも思いますが、ミスに気づきやすいのでこの記法に揃えています。

### FROM句内のインデントでテーブル構造を表現してみる。  
これは、私の好みの問題。
属する組織などのやりかたに沿って欲しい。

```
sales
  │
  └──sales_belonging
  │      │
  │      └──companies
  │
  └──sales_contacts
```

```SQL
from
  sales
  left outer join
    sales_contact
    on  sales.id = sales_contact.sales_id
  left outer join
    sales_belonging
    on  sales.id = sales_belonging.sales_id
    left outer join
      companies
      on  sales_belonging.company_id = companies.id
```
これが、もっと複雑にテーブルJOINしだすと以外に便利だったりする。

## 筆者的最終形

```SQL
select
  salses.id
  , sales.name
  , companies.name
  , sales_contact.mail
from
  sales
  left outer join
    sales_contact
    on  sales.id = sales_contact.sales_id
  left outer join
    sales_belonging
    on  sales.id = sales_belonging.sales_id
    left outer join
      companies
      on  sales_belonging.company_id = companies.id
where
  (
    sales.age > 20
    or sales.age < 40
  )
  and sales_contact.mail is not null
```
## 後述
こんなこと、と思うかもしれないけれど・・・。 
正常な動作を実現するため、正確にレビューを受けるため、他の人に引き継ぐときに困らないため、そしてなにより明日の自分のために必要な技術だと思っています。

## テーブル定義
Table: Sales

| id | name | age |
| --- | --- | ---|
| int | varchar | int |

Table: sales_contacts
id = sales_id

| id | phone | mail |
| --- | --- | --- |
| int | varchar | varchar |

Table: sales_belongings
sales : sales_belongings = 1 : N

| id | sales_id | conpany_id |
| --- | --- | --- |
| int | int | int |

Table: company

| id | name |
| --- | --- |
| int | carchar |

## 別途参考
[クックパッドさんの記事](http://techlife.cookpad.com/entry/2016/11/09/000033)