select

作成日: 2017-03-28
最終更新日:

1.はじめに

SQL はデータ定義言語とデータ操作言語に分かれる。データ操作のなかで大きな存在を占めるのが select である。

2. select の基本

select の基本は「どのテーブルから」、「どんな条件を満たす行を」、「どの列から取り出すか」だ。 それを書いてみよう。

select 作曲家, 交響曲数    from 交響曲情報  where 交響曲数 >= 9 

ここでテーブル"交響曲情報"は次のようなものだとする。

作曲家交響曲数
モーツァルト41
ベートーヴェン9
メンデルスゾーン5
シューマン4
ブラームス4
マーラー9
ショスタコーヴィチ15

次の出力が得られる

作曲家交響曲数
モーツァルト41
ベートーヴェン9
マーラー9
ショスタコーヴィチ15

ここで、どの列から取り出すか、については複数列を指定できた。では、テーブルは複数指定できるのだろうか。行の条件は複数指定できるのだろうか。 そこを見ていこう。

3. テーブルの複数指定と選択

こんどは、次のテーブル"ピアノ協奏曲情報"があるとしよう。

作曲家ピアノ協奏曲数
モーツァルト27
ベートーヴェン5
メンデルスゾーン2
シューマン1
ブラームス2
ショスタコーヴィチ2

ここで、次のような SQL を書いたとしたら、どのような結果が得られるだろうか。

select 作曲家, 交響曲数, ピアノ協奏曲数    from 交響曲情報, ピアノ協奏曲情報 where 交響曲数 >= 9 

素人だったら(という素人の私がこうなってくれればいいな、という願望をこめれば)こんな表が出るのではないかと想像できる。

作曲家交響曲数協奏曲数
モーツァルト4127
ベートーヴェン95
マーラー9
ショスタコーヴィチ152

3.1 クロス結合

ここで都合により、次のような SQL を書いたとする。列はすべて表示するので * を使う。where を使った交響曲数による制限は求めない

sqlite> select * from 交響曲情報, ピアノ協奏曲情報
作曲家交響曲数作曲家ピアノ協奏曲数
モーツァルト41モーツァルト27
モーツァルト41ベートーヴェン9
モーツァルト41メンデルスゾーン2
(中略)
ショスタコーヴィチ15モーツァルト27
ショスタコーヴィチ15ベートーヴェン9
ショスタコーヴィチ15メンデルスゾーン2
ショスタコーヴィチ15シューマン1
ショスタコーヴィチ15ブラームス2
ショスタコーヴィチ15ショスタコーヴィチ2

なんか変だ。2つのテーブルの作曲家の組み合わせが表示されてしまっている。このような結合をクロス結合という。 同じ作曲家は同じ作曲家として結合してほしい。それにはどうするか。

3.2 内部結合

コンピュータには、このカラムとあのカラムが等しいときを(またそのときに限って)検索対象とする、ということを伝えることはできる (というより、そうしないといけない。コンピュータは融通が利かないから)。 それには、from でテーブルを指定するときに、結合するための用語を用いる。 A INNER JOIN B ON A.カラム名 = B.カラム名 とする。

実際にはどうか。

sqlite> select * from 交響曲情報 INNER JOIN ピアノ協奏曲情報 on 交響曲情報.作曲家 = ピアノ協奏曲情報.作曲家
作曲家交響曲数作曲家ピアノ協奏曲数
モーツァルト41モーツァルト27
ベートーヴェン9ベートーヴェン9
メンデルスゾーン5メンデルスゾーン2
シューマン4シューマン2
ブラームス4ブラームス2
ショスタコーヴィチ15ショスタコーヴィチ2

マーラーの名前がない。これは、ピアノ協奏曲情報にマーラーの名前がないからだ。共通する情報だけを結合するのが INNER JOIN の仕様だ。 ではマーラーの名前を出すにはどうするか。

3.3 左外部結合

マーラーの名前を出すには、左外部結合と呼ばれる結合を用いる。SQL では LEFT OUTER JOIN を使う。LEFT JOIN でもよい。

sqlite> select * from 交響曲情報 LEFT OUTER JOIN ピアノ協奏曲情報 on 交響曲情報.作曲家 = ピアノ協奏曲情報.作曲家
作曲家交響曲数作曲家ピアノ協奏曲数
モーツァルト41モーツァルト27
ベートーヴェン9ベートーヴェン9
メンデルスゾーン5メンデルスゾーン2
シューマン4シューマン2
ブラームス4ブラームス2
マーラー9
ショスタコーヴィチ15ショスタコーヴィチ2

こんどはマーラーの名前が来ている。

3.4 右外部結合と全外部結合

では、ピアノ協奏曲情報が次のとおりだったらどうだろうか。

作曲家ピアノ協奏曲数
モーツァルト27
ベートーヴェン5
メンデルスゾーン2
シューマン1
ブラームス2
ラヴェル2
ショスタコーヴィチ2

ラヴェルは交響曲を書いていない。だから、INNER JOIN でも、LEFT OUTER JOIN でも表せない。この場合は右外部結合を表す RIGHT OUTER JOIN を使う。 ただ、RIGHT OUT JOIN では、こんどはマーラーが出てこない。 どちらも出てくるようにするには、全外部結合を表す FULL OUTER JOIN を用いる。

4. 結合した表からの選択

ここまでで、二つの表を結合した結果がどうなるかがわかったので、交響曲が 9 曲以上ある作曲家の氏名と情報を見てみよう。

sqlite> select 作曲家, 交響曲数, ピアノ協奏曲数 
           from 交響曲情報 LEFT OUTER JOIN  ピアノ協奏曲情報 ON 交響曲情報.作曲家=ピアノ協奏曲情報.作曲家
           where 交響曲数 >= 9 ;
Error: ambiguous column name: 作曲家

「作曲家」があいまいだというのだ。コンピュータに言わせれば、テーブル"交響曲情報"の作曲家なのか、 テーブル"ピアノ協奏曲情報"の作曲家なのかが区別がつかない、ということなのだ。そこで区別をしないといけない。

sqlite> select 交響曲情報.作曲家, 交響曲数, ピアノ協奏曲数 
           from 交響曲情報 LEFT OUTER JOIN  ピアノ協奏曲情報 ON 交響曲情報.作曲家=ピアノ協奏曲情報.作曲家
           where 交響曲数 >= 9 ;
作曲家交響曲数ピアノ協奏曲数
モーツァルト4127
ベートーヴェン95
マーラー9
ショスタコーヴィチ152

4.1 where と比較演算子

上記の場合は比較演算子 >= を使った。ほかにも比較演算子は多くある。注意すべきは、NULL との比較では比較演算子は使えない。 NULL と同じ場合は IS NULL を、NULL ではない場合は IS NOT NULL である。

5. 応用:グループの利用

グループごとに集計をすることができる。別の表で考えよう。作曲家情報というテーブルを下に示す。なお、ジャンルの選択は半ば無作為、半ば恣意的である。

作曲家ジャンル曲数
モーツァルト歌劇21
モーツァルト交響曲41
モーツァルトピアノ協奏曲27
モーツァルトクラリネット協奏曲1
ベートーヴェン歌劇1
ベートーヴェン交響曲9
ベートーヴェンピアノ協奏曲5
マーラー交響曲 9
ショスタコーヴィチ歌劇4
ショスタコーヴィチ交響曲15
ショスタコーヴィチピアノ協奏曲2
ショスタコーヴィチチェロ協奏曲2
ショスタコーヴィチピアノ五重奏曲1

ではそれぞれの作曲家が何種類のジャンルで作品を作っているかを知るにはどうしたらよいか。

sqlite> select 作曲家, COUNT(*) FROM 作曲家情報 GROUP BY 作曲家
作曲家COUNT(*)
モーツァルト4
ベートーヴェン3
マーラー1
ショスタコーヴィチ5

まりんきょ学問所コンピュータの部屋システムの部屋データベースSQL > select


MARUYAMA Satosi