[SQL]サブクエリに名前をつけて使用する方法

##1,始めに
この記事はプログラミング初心者が**アウトプットの練習**として書いたものです。ここ間違えているよ、とか、ここを改善したら読みやすくなるよ、などアドバイスがありましたら、ぜひコメントにてご教授ください。
##2,書き方
問題に対して答えのSQL提示し、それを解説すると相手に伝わりやすいのかなと思います。
##3,使用環境
PostgreSQL 10 (pgAdmin4 ver,4.2)

####使用するテーブル
テーブル名(human_list)

|名前(name) |年齢(age)|性別(gender) |誕生日(birthday)  |
|:---------:|:---:|:--------:|:---------------:|
|Aさん|25|男|1989-02-20|
|Bさん|59|男|1955-08-01|
|Cさん|30|女|1968-07-16|
|Dさん|67|男|1948-01-29|
|Eさん|28|男|1986-07-20|
|Fさん|35|女|1979-12-24|
|Gさん|27|女|1987-11-03|

####Q.問題
20歳～30歳の男性と、25歳～35歳の女性のうち同じ月生まれの社員を出力しなさい。
※1.男性と女性それぞれから探したい。
※2.列名も下記のように変更。
###A.解答例
この問題に対して出したい答えは以下になります。

|名前(男)|年齢(男)|誕生日(男)|名前(女)|年齢(女)|誕生日(女)|
|:---:|:---:|:---:|:---:|:---:|:---:|
|Eさん|28|1986-07-20|Cさん|30|1968-07-16|

####A.解答例のSQL文
```SQL
SELECT man.name AS 名前（男）, man.age AS 年齢（男）, man.birthday AS 誕生日（男）,
woman.name AS 名前（女）, woman.age AS 年齢（女）, woman.birthday AS 誕生日（女）
FROM (SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender = '男' AND age >= 20 AND age <= 30) man,
(SELECT name,age,birthday,TO_CHAR(birthday,'MM') Months
FROM human_list WHERE gender ='女' AND age BETWEEN 25 AND 35)woman
WHERE man.months = woman.months
```
<br>
めちゃくちゃわかりずらいですね。
分解するとこうなります。
<br>


```SQL
SELECT man.name AS 名前（男）, man.age AS 年齢（男）, man.birthday AS 誕生日（男）,
woman.name AS 名前（女）, woman.age AS 年齢（女）, woman.birthday AS 誕生日（女）
```

```SQL
FROM (SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender = '男' AND age >= 20 AND age <= 30) man,
(SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender ='女' AND age BETWEEN 25 AND 35)woman
```

```SQL
WHERE man.months = woman.months
```

ちょっとずつ見えてきましたか？長ったらしく書いてありますが、各文の先頭に注目してください。要は
**SELECT (1)  + FROM (2)  + WHERE (3)**
と書いてあるだけなんですね。今回の目的であるサブクエリは(2)に記述されています。
 (1) から順に見ていきましょう。

###SELECT(1)

```SQL
SELECT man.name AS 名前（男）, man.age AS 年齢（男）, man.birthday AS 誕生日（男）,
woman.name AS 名前（女）, woman.age AS 年齢（女）, woman.birthday AS 誕生日（女）
```
SELECTの基本部分ですね、ここに表示したい列名を書いています。
man.nameやman.ageなどは後で解説しますが、ここもサブクエリに関係しています。
ASを使い表示する列名を変更しています。

###FROM(2)
```SQL
FROM (SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender = '男' AND age >= 20 AND age <= 30)man,
(SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender ='女' AND age BETWEEN 25 AND 35)woman
```

(2)の解説ですが、先にサブクエリをおさらいしましょう。
サブクエリとは・・・SQL文の中にある別のSQL文である。（）で囲って使用。
だから1行目や3行目の「SELECT」はサブクエリってことになります。

じゃあなんでFROMが3つもあるのかってことですが、1つめのFROMは文全体のFROMです。
ですので、分解した今意味はありませんので、無視してください。

まだ分かりづらいのでさらに分解します。

```SQL
(SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender = '男' AND age >= 20 AND age <= 30)man,
```
```SQL
(SELECT name,age,birthday,TO_CHAR(birthday,'MM')Months
FROM human_list WHERE gender ='女' AND age BETWEEN 25 AND 35)woman
```

ほぼ同じSELECTのサブクエリを2回使用していることがわかったのではないでしょうか。

注目すべきは閉じ括弧のあとにある「Months」と「man」「woman」です。
これは私の解釈でしかありませんが、閉じ括弧の部分に名前を付けているのではないでしょうか。
他の方はASを付けているようですが、省略しても使えますね。

つまり**TO_CHAR(birthday,'MM')**に**「Months」**
**サブクエリのSELECT文**それぞれに**「man」「woman」**と付けているのです。

ここで最初に出てきたman.nameやman.ageが関係してくるのです。
man.nameやman.ageとは
ここの「man」「woman」と名付けられたSELECT文の中のnameとageだったわけですね。

###WHERE (3)
```SQL
WHERE man.months = woman.months
```
最後のWHEREですが、もうお分かりですね。
「man」のmonthsと「woman」のmonthsが同じである、行を表示、ということになります。

以上です。

##3,最後に
いかかでしたでしょうか？アウトプットの練習としてこれを書きましたが、伝わりましたか？
次はJavaでも書いてみましょうかね、SQLより説明難しそうだな・・・。<br>
それではここまで読んでくださってありがとうございました！