はじめに
 「MySQLで分析関数を模倣」シリーズに続いて、MySQLでOracleのSQLを模倣する方法を紹介したいと思います。本稿では、minus、intersect、完全外部結合、パーティション化された外部結合と同じ結果を取得するSQLを扱います。
対象読者
- MySQLで、OracleのSQLと同じ結果を取得するSQLを書きたい方
 - OracleのSQLの理解を深めたい方
 
必要な環境
本稿で扱うSQLは、MySQL 5.1.28で動作確認しました。ソースコードはOracle 10.2.0.1.0でも動作確認しました。その他、次の環境でも応用が可能です。
- PostgreSQL
 - SQL Server
 - DB2
 
1. minus
 minusは、差集合演算を行います。Oracle以外のデータベースでは、exceptで実装されています(標準SQLでexceptとして定義されているため)。
MySQLで同じ結果を取得してみましょう。まずは、テーブルのデータと、出力結果を考えます。
| PKey | Val | 
| 1 | 2 | 
| 2 | null | 
| 3 | null | 
| 4 | 8 | 
| PKey | Val | 
| 1 | 2 | 
| 2 | null | 
| 3 | 5 | 
| 4 | 9 | 
 TBL1に存在して、TBL2に存在しない行を出力します。言いかえれば、Oracleの下記のminusを使ったSQLと同じ結果を取得します。
select PKey,Val from TBL1 minus select PKey,Val from TBL2;
| PKey | Val | 
| 3 | null | 
| 4 | 8 | 
 TBL1に存在して、TBL2に存在しない行を出力するので、exists述語を使えばいいと考え、答えは下記となります。
select PKey,Val
  from TBL1 a
 where not exists(select 1 from TBL2 b
                   where b.PKey <=> a.PKey
                     and b.Val  <=> a.Val);
 exists述語を使う方法の、SQLのイメージは下記です。

 別の考え方として、下記のようにunion allとgroup byを使う方法もあります。
select PKey,Val
from (select 1 as ID,PKey,Val from TBL1 union all
      select 2 as ID,PKey,Val from TBL2) a
group by PKey,Val
having max(ID) = 1;
 union allとgroup byを使う方法の、SQLのイメージは下記です。

