他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

2.6. テーブル間を結合

ここまでの問い合わせは、一度に1つのテーブルにのみアクセスするものでした。 問い合わせは、一度に複数のテーブルにアクセスすることも、テーブル内の複数の行の処理を同時に行うようなやり方で、1つのテーブルにアクセスすることも可能です。 一度に同一のテーブルまたは異なるテーブルの複数の行にアクセスする問い合わせは、結合問い合わせと呼ばれます。 例として、すべての気象データを関連する都市の位置情報と一緒に表示したい場合が挙げられます。 それを行うためには、weatherテーブルの各行のcity列を、citiesテーブルの全ての行のname列と比較し、両者の値が一致する行の組み合わせを選択しなければなりません。

注記

これは概念的なモデルでしかありません。 実際の結合は通常、1つひとつの行の組み合わせを比べるよりも、もっと効率的な方法で行われます。 しかし、これはユーザからはわかりません。

これは、以下の問い合わせによって行うことができます。

SELECT *
    FROM weather, cities
    WHERE city = name;

     city      | temp_lo | temp_hi | prcp |    date    |     name      | location
---------------+---------+---------+------+------------+---------------+-----------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
 San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
(2 rows)

この結果について2つのことに注目してください。

練習:  WHERE句を省略した場合のこの問い合わせの意味を決定してください。

列がすべて異なる名前だったので、パーサは自動的にどのテーブルの列かを見つけることができました。 2つのテーブルで列名が重複している場合は、以下のようにどちらの列を表示させたいかを示すために列名を修飾しなければなりません。

SELECT weather.city, weather.temp_lo, weather.temp_hi,
       weather.prcp, weather.date, cities.location
    FROM weather, cities
    WHERE cities.name = weather.city;

結合問い合わせではすべての列名を修飾するのが良いやり方であると一般に考えられています。 そうすれば、テーブルのいずれかに後で重複する名前を持つ列が追加されても、問い合わせが失敗しません。

ここまでに示したような結合問い合わせは、以下のように別の形で表すことができます。

SELECT *
    FROM weather INNER JOIN cities ON (weather.city = cities.name);

この構文は先の例よりも一般的に使用されるものではありませんが、以降の話題の理解を助けるためにここで示しています。

ここで、どのようにすればHaywardのレコードを得ることができるようになるのかを明らかにします。 実行したい問い合わせは、weatherをスキャンし、各行に対して、cities行に一致する行を探すというものです。 一致する行がなかった場合、citiesテーブルの列の部分を何らかの空の値に置き換えたいのです。 この種の問い合わせは外部結合と呼ばれます (これまで示してきた結合は内部結合です)。 以下のようなコマンドになります。

SELECT *
    FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);

     city      | temp_lo | temp_hi | prcp |    date    |     name      | location
---------------+---------+---------+------+------------+---------------+-----------
 Hayward       |      37 |      54 |      | 1994-11-29 |               |
 San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
 San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
(3 rows)

この問い合わせは左外部結合と呼ばれます。 結合演算子の左側に指定したテーブルの各行が最低でも一度出力され、一方で、右側のテーブルでは左側のテーブルの行に一致するもののみが出力されるからです。 右側のテーブルに一致するものがない、左側のテーブルの行を出力する時、右側のテーブルの列は空の値(NULL)で置換されます。

練習:  右外部結合や完全外部結合も存在します。 これらが何を行うかを考えてください。

テーブルを自分自身に対して結合させることができます。 これは自己結合と呼ばれます。 例として、他の気象データの気温範囲内にある気象データを全て取り出すことを考えます。 weather各行のtemp_lotemp_hiを、他のweather行のtemp_lotemp_hi列とを比較しなければなりません。 以下の問い合わせを使用して行うことができます。

SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high,
    W2.city, W2.temp_lo AS low, W2.temp_hi AS high
    FROM weather W1, weather W2
    WHERE W1.temp_lo < W2.temp_lo
    AND W1.temp_hi > W2.temp_hi;

     city      | low | high |     city      | low | high
---------------+-----+------+---------------+-----+------
 San Francisco |  43 |   57 | San Francisco |  46 |   50
 Hayward       |  37 |   54 | San Francisco |  46 |   50
(2 rows)

ここで、結合の左側と右側を区別することができるように、weatherテーブルにW1W2というラベルを付けています。 また、入力量を省くために、他の問い合わせでもこの種の別名を使用することができます。 以下に例を示します。

SELECT *
    FROM weather w, cities c
    WHERE w.city = c.name;

こういった形の省略はかなりよく行われます。