SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

MySQLでOracleのSQLを模倣する

MySQLでOracleのSQLを模倣1
(集合演算編)

MySQLで、OracleのSQLと同じ結果を取得する1

ダウンロード SourceCode (2.5 KB)

2. intersect

 intersectは、積集合演算を行います。MySQLで同じ結果を取得してみましょう。まずは、テーブルのデータ(前問と同じ)と、出力結果を考えます。

TBL1
PKey Val
1 2
2 null
3 null
4 8
TBL2
PKey Val
1 2
2 null
3 5
4 9

 TBL1に存在して、TBL2にも存在する行を出力します。言いかえれば、Oracleの下記のintersectを使ったSQLと同じ結果を取得します。

intersectを使ったSQL
select PKey,Val from TBL1 intersect
select PKey,Val from TBL2;
出力結果
PKey Val
1 2
2 null

 場合によっては、下記のような自然結合が使えるのですが、集合演算は、null同士を等しいと判定するのに対して、自然結合は、null同士を等しいと判定しないので、この場合は、自然結合で正しい結果を取得できません。

自然結合を使う方法(この場合は間違い)
select PKey,Val
  from TBL1 NATURAL JOIN TBL2;
自然結合を使った出力結果
PKey Val
1 2

 前問と似た考え方で、TBL1に存在して、TBL2にも存在する行を出力するので、exists述語を使えばいいと考え、答えは下記となります。

exists述語を使う方法
select PKey,Val
  from TBL1 a
 where exists(select 1 from TBL2 b
               where b.PKey <=> a.PKey
                 and b.Val  <=> a.Val);

 exists述語を使う方法の、SQLのイメージは下記です。

SQLのイメージ
SQLのイメージ

 別の考え方として、下記のようにunion allとgroup byを使う方法もあります。

union allとgroup byを使う方法
select PKey,Val
from (select PKey,Val from TBL1 union all
      select PKey,Val from TBL2) a
group by PKey,Val
having count(*) = 2;

 union allとgroup byを使う方法の、SQLのイメージは下記です。

SQLのイメージ
SQLのイメージ

3. 完全外部結合

 左外部結合と右外部結合の和集合を取得する完全外部結合は、Oracle9iから使用可能になりました。MySQLで同じ結果を取得してみましょう。まずは、テーブルのデータと、出力結果を考えます。

FJoin1
PKey Val
1 aaa
2 bbb
FJoin2
PKey Val
1 ccc
3 ddd

 Oracleの下記の完全外部結合を使ったSQLと同じ結果を取得します。

完全外部結合を使ったSQL
select a.PKey as aPKey,a.Val as aVal,
       b.PKey as bPKey,b.Val as bVal
  from FJoin1 a full join FJoin2 b
    on (a.PKey=b.PKey)
order by nvl(a.PKey,b.PKey);
出力結果
aPKey aVal bPKey bVal
1 aaa 1 ccc
2 bbb null null
null null 3 ddd

 完全外部結合は、左外部結合と右外部結合の和集合を取得することに注目して、答えは、下記となります。

外部結合を使う方法
select a.PKey as aPKey,a.Val as aVal,
       b.PKey as bPKey,b.Val as bVal
  from FJoin1 a Left Join FJoin2 b
    on (a.PKey=b.PKey)
union
select a.PKey as aPKey,a.Val as aVal,
       b.PKey as bPKey,b.Val as bVal
  from FJoin1 a right Join FJoin2 b
    on (a.PKey=b.PKey);

 外部結合を使う方法の、SQLのイメージは下記です。

SQLのイメージ
SQLのイメージ

 別の考え方として、下記のようにunion allとgroup byを使う方法もあります。

union allとgroup byを使う方法
select max(case ID when 1 then PKey end) as aPKey,
       max(case ID when 1 then Val  end) as aVal,
       max(case ID when 2 then PKey end) as bPKey,
       max(case ID when 2 then Val  end) as bVal
from (select 1 as ID,PKey,Val from FJoin1 union all
      select 2 as ID,PKey,Val from FJoin2) d
group by PKey;

 union allとgroup byを使う方法の、SQLのイメージは下記です。

SQLのイメージ
SQLのイメージ

次のページ
4. パーティション化された外部結合

この記事は参考になりましたか?

この記事の著者

山岸 賢治(ヤマギシ ケンジ)

趣味が競技プログラミングなWebエンジニアで、OracleSQLパズルの運営者。AtCoderの最高レーティングは1204(水色)。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3906 2009/05/28 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー