トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
10-219 元集合の重複を残す差集合演算
SQLパズル
TableX TableY TableZ
Val Val Val
--- --- ---
1 1 2
2 2 3
3 5 5
4 6
TableXのValと、TableYのValの和集合(重複を残す和集合)
と
TableZとの差集合
を求める。
ただし、差集合演算において、元集合の重複は残す。
出力結果
Val
---
1
1
4
6
データ作成スクリプト
create table TableX(Val primary key) as
select 1 from dual union
select 2 from dual union
select 3 from dual union
select 4 from dual;
create table TableY(Val primary key) as
select 1 from dual union
select 2 from dual union
select 5 from dual union
select 6 from dual;
create table TableZ(Val primary key) as
select 2 from dual union
select 3 from dual union
select 5 from dual;
SQL
--■■■最初のselectを括弧でくくらない方法■■■
select * from TableX
minus
select * from TableZ
union all
(select * from TableY
minus
select * from TableZ)
order by 1;
--■■■最初のselectを括弧でくくる方法■■■
(select * from TableX
minus
select * from TableZ)
union all
(select * from TableY
minus
select * from TableZ)
order by 1;
解説
Boolean algebra
のSet Versionの2番 (集合の分配法則)
A∩(B∪C) = (A∩B)∪(A∩C)
を使って導いた等式の、
_ _ _
(X∪Y) ∩ Z = (X∩Z) ∪ (Y∩Z)
を使ってます。(ベン図を脳内でイメージすると分かりやすいでしょう)
集合の分配法則は、
ブール代数の分配法則とセットで覚えるといいでしょう。
_ _ _
(X+Y)*Z = (X*Z) + (Y*Z)
集合論――数学の「集合論」に,RDBの正体を見る
なお、
A∩(B∪C) = (A∩B)∪(A∩C) に、双対の原理を適用すると
A∪(B∩C) = (A∪B)∩(A∪C) を得ることができます。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
not existsを使うのが良さそうですが、
使い捨てのSQLで、列数が多くて、
select *
を使いたいときに、使い道があるかもしれません。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
最初に括弧を使う形は、文法上正式に許可されているか不明です。
UNION [ALL]、INTERSECTおよびMINUS演算子
(select 1 from dual
union
select 2 from dual)
union all
(select 1 from dual
union
select 2 from dual);