スポンサーリンク

【SQL】join動作まとめ

スポンサーリンク

すぐに忘れてしまうので、まとめます。

Table

null nullなんていう表は本来ありませんが、練習のため追加します。

直積(cross join)

以下の結合等の元となる直積。

select * from N cross join S;

以下と同じ

select * from N,S;

結合((inner) join)

select * from N join S on N.sid = S.sid;

sidが同一のところのみ結合される。なお、一方でもnullの場合は評価値はnullになるので、N.sidやS.sidのいずれかがnullのカラムは抽出されません。また、両方がnullの場合でもnullを返すので同様です。

同じ表現は以下。

select * from N inner join S on N.sid = S.sid;
select * from N,S where N.sid = S.sid;

innerはdefaultでも明示的に指定しなくともよい。また、直積からそのままwhere句で抽出操作自体が結合の動作なので同様の結果が得られる。

自然結合(natural join)

select * from N natural join S;

結合に使用したsidのうち一方が消去される。usingを使用した以下と同様

select * from N inner join S using (sid);

外部結合

select * from N left outer join S on N.sid = S.sid;

分かりにくくなってしまったが、4番目のnullは上述した通り、null同士で一致したから表示されたのではなく、外部結合なのでnullに対応するものが確認できなったので、nullとして表示されているだけである。このように外部結合では元の表と追加の処理を加えない限り行数は同一になる。

以下と同じ。なお、出力されるカラムの順番は異なる

select * from S right outer join N on N.sid = S.sid;

追加

join区で一方のテーブルのみの条件を加えた場合、条件に適合する部分のみ値を持って結合され、適合しない場合は結合部はnullとなる。

select * from N left outer join S on N.sid = S.sid and n.id = 1;
select * from N left outer join S on N.sid = S.sid and S.sid = 'b';

自然外部結合

select * from N natural left outer join S;

以下と同じ。

select * from N left outer join S using (sid);

和演算(Union)

集合演算については特に何の意味もないので例として分かりにくいかもしれない。

select sid from N union select sid from S;

defaultで重複した行は消去される

select sid from N union all select sid from S;

allをつけることで重複消去を無効に可能

差演算(except)

select sid from N except select sid from S;

まったく同じものを引いているので何も表示されません。分かりにくいので以下のように’c’だけ引いてみます。

select sid from N except select ('c');

こちらについてもdefaultでは重複行は消去されることに注意してください。少しわかりにくいですが、以下の例で確認できます。

(select sid from N union all select sid from S) except all select ('c');
(select sid from N union all select sid from S) except select ('c');

共通演算

select sid from N intersect select sid from S;

共通項を取り出します。今回は同一なのですべて表示されています。

集合演算全体に言えることですが、行の順番は関係ありません。一方で、同じレコードが含まれる場合、出力される数は一致するレコード数までで、どちらかの最大同レコードとなります。何がいいたいかというと、

(select sid from N union all select ('d') union all select ('c')) intersect all (select sid from S);

intersect all

の結果は以下になります。

cは2つあるのに1つしか出力されていません。しがって1:1でレコードを比較していくのであって、1:多で比較するわけではありません。まぁ通常はallを指定しないで出すでしょうから気にする必要はないと思われます。

タイトルとURLをコピーしました