以前の記事
結合(JOIN)
結合は1つのクエリで複数テーブルのデータを扱いたいときに利用します。
結合クエリの構文 SELECT <値式のリスト> FROM <テーブル名のリスト> WHERE ...;
まずは、以下のような結合クエリをみていきます。これはstudentとclub_memberを結合して、全ての列を出力するクエリです。この結合の結果は、2つのテーブルのレコードにある全ての組み合わせを網羅したものになります。studentの3人の学生(レコード)に対して、それぞれclub_memberの3つのレコードとの組み合わせが考えられるので、合計9レコードが出力されます。
SELECT * FROM student, club_member;
こういった結合をクロス結合と呼びます。結合は、テーブル同士の結合の仕方によってクロス結合(CROSS JOIN)、内部結合(INNER JOIN)、外部結合(OUTER JOIN)という3種類に分かれます。SQLで、結合は非常に面白いところだと思いますし、一方で若干とっつきにくいところでもあるので、ここで立ち止まって理解に時間をかけても良いと思います。
INNER JOIN
内部結合(INNER JOIN)は、クロス結合の部分集合です。内部結合の結果は、クロス結合の結果からある結合条件を満たす行だけに絞ったものになります。結合条件は、等値結合 (=)と非等値結合(>、 <、 <>, !=、...)の2種類に分類されます。以下のクエリは、学生とクラブメンバーのクロス結合の結果から、学生テーブルのsidとクラブメンバーテーブルのsidが等しいレコードのみに絞って出力します。
SELECT s.*, cm.cid FROM student s, club_member cm WHERE s.sid = cm.sid;
JOIN構文
外部結合に行く前に、JOINの2種類の表記方法を紹介します。1つは、今まで見てきたように、カンマ区切りでテーブルを区切るやり方です。もう1つは、カンマの代わりに明示的に結合の種類を指定するやり方です。また、内部結合を明示的に指定する場合は、WHEREの代わりにONで結合条件を記述します。
OUTER JOIN
外部結合には3種類あります。まずは、左外部結合(LEFT OUTER JOIN)から紹介します。これは、内部結合と同様に、クロス結合の結果から結合条件を満たす行を全て返します。ただし、結合条件にマッチするかに関わらず、左側のテーブルの行は全て返すというところが内部結合と異なるところです。
下のクエリは、先ほどの内部結合クエリと結合の種類以外は同じです。結果を見てみると、cidが不明(NULL)の学生が含まれています。どういうことかと言うと、まず学生がクラブに参加していない場合、クラブメンバーテーブルに、その学生のsidは存在しません。そのため、内部結合の場合は、クラブ不参加の学生はクエリ結果から除外されます。
しかし、左外部結合クエリは、学生テーブル(左)のレコードを全て残すので、クラブメンバーテーブル(右)のどのレコードともマッチしなかった学生も含まれます。そして、マッチしなかった(クラブ不参加の)学生レコードには、結合時に埋められなかった列(cid)が存在するので、代わりにNULLが入ります。
SELECT s.*, cm.cid FROM student s LEFT OUTER JOIN club_member cm ON s.sid = cm.sid;
外部結合の種類は、左外部結合(LEFT OUTER JOIN)、右外部結合(RIGHT OUTER JOIN)、完全外部結合(FULL OUTER JOIN)の3種類です。左と右の違いは、どちらをマスターテーブルに選ぶかです。マスターテーブルのデータ(行)はすべて残ります。そして、両方ともマスターなのが、完全外部結合です。
ちなみに、あるテーブルの結合対象が自身になる結合は、自己結合と呼ばれます。同じテーブルに対して別名をつけて結合するというものです。
クエリを書いてみよう
31アイスクリームのデータベースを用意しました。このデータベースから、Q1からQ3で求められているデータを、SELECT文を用いて取得してみましょう。サンプル解答は最後のページに記載しています。
環境セットアップ
sql_learning repositoryのREADMEに従って、MySQL環境を用意し、クエリを実行してください。
問題
Q1. 31アイスクリームのフレーバーの組み合わせ一覧を出力してください("ダブルサイズ"の選択肢をください)。ただし、同じフレーバーはなしです。同じ組み合わせも一覧に含めないでください。加えて、カロリーの合計も出してほしいです。
Q2. 上の一覧から合計カロリーが350以下で、ELEGANTなフレーバーが含まれるペアに絞り、その中から一番カロリーが低いペアを出してほしいです。
Q3. 上と同様に、最適なトリプルの組み合わせを出してほしいです。