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