はじめに
「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のイメージは下記です。

