A 回答 SELECT文の結果は,検索条件やジョインの種類によって変わってきます。
![]() |
| 図1●テーブルの内容と誤ったSELECT文の例 社員テーブルと所属テーブルの2つのテーブルがある。この2つのテーブルに対して図中の3つのSELECT文を作成したが,(1)と(2)は所望の結果は得られず,(3)の結果は同じ内容のレコードが複数返ってきてしまう |
ジョインの種類を使い分けよう
図1(1)[拡大表示]は「全社員の名前と所属名称を検索する」ために作成したSELECT文ですが,このSELECT文では所属IDが「2」や「NULL」の社員は検索できません。全社員が検索できないため,誤ったSELECT文になっています。
この例で注意しなければならないのは,結合カラムになっている所属IDカラムの値です。社員テーブルの所属IDカラムには「1,2,3,NULL」の4つの値がありますが,所属テーブルの所属IDカラムは「1,3,4」の3つの値です。社員テーブルにある「2」や「NULL」は所属テーブルになく,所属テーブルにある「4」は社員テーブルにありません。このようなテーブルの場合,ジョインの種類によって検索結果は変わってしまいます。ここで言っているジョインの種類とは,インナー・ジョイン(内部結合)やアウター・ジョイン(外部結合)のことです。
![]() |
| 図2●インナー・ジョインとアウター・ジョインの動き インナー・ジョイン(内部結合)は結合カラムが一致するレコードだけを結合し,アウター・ジョイン(外部結合)は結合カラムが一致しないレコードも結合対象とする |
所属先が見つからなくても社員が検索されるようにするには,インナー・ジョインではなく,アウター・ジョインを指定する必要があります(同右[拡大表示])。アウター・ジョインを使えば,結合カラムが同じにならなくても検索結果に含めることができます。この例では,社員テーブルの全レコードを検索結果に含むようにしたいため,
SELECT 社員.名前,所属.名称
FROM 社員 LEFT OUTER JOIN 所属
ON 社員.所属ID = 所属.所属ID
と記述します。FROM句の2つのテーブル名の間に「LEFT OUTER JOIN」と記述すると,左アウター・ジョインとなり,左側(社員)テーブルの全レコードを含む結果になります。「LEFT JOIN」と記述するRDBMSもあります。ちなみに,「RIGHT OUTER JOIN」または「RIGHT JOIN」とすると,右側(所属)テーブルの全レコードを含む結果になります。
NULLの扱いには注意が必要
図1(2)[拡大表示]は「所属先が『総務』以外の社員名を検索する」ために作成したSELECT文です。社員テーブルの所属IDが「1」ではない社員を検索しなければなりませんが,このSELECT文では所属IDが「NULL」の社員は検索できません。
例のように検索条件に「社員.所属ID <> 1」とした場合,社員テーブルの所属IDカラムが「1」ではない社員を検索しますが,その際「NULL」のレコードは検索されません。NULLのカラムを持つレコードを検索するには,「ISNULL」という条件を指定する必要があります。今回の例の場合,
SELECT 社員.名前 FROM 社員
WHERE 社員.所属ID <> 1
OR 社員.所属ID IS NULL
とすれば,目的の結果を検索することができます。
図1(3)[拡大表示]は,「1990年以降に入社した社員が所属する部署名を検索する」ために作成したSELECT文です。おそらく「人事」という結果を期待していると思われますが,このSELECT文では「人事」「人事」となってしまいます。2つの同じ結果が出力されるのです。
図1(3)は文法的にも意味的にも正しいのですが,検索結果のレコード数に対する配慮が足りません。1990年以降に入社した社員は4人で,そのうち所属先が明らかなのは2人です。どちらも「人事」に所属しているため,検索結果は2レコード出力されます。このように同じ結果を重複して出力しないようにするには,「DISTINCT」というキーワードを付けます。具体的には,
SELECT DISTINCT 所属.名称 FROM
社員,所属 WHERE 社員.所属ID = 所属.
所属ID AND 社員.入社年度 >= 1990
とすれば目的の結果を取り出すことができます。


