導入
「高額商品のリストと、在庫切れ商品のリストを、1つにまとめたい」。2つの SELECT の結果どうしを、足したり・共通部分を取ったり・引いたりできるのが集合演算です。ベン図の「和・積・差」をそのまま SQL でやるイメージです。
説明
3つの演算があります。いずれも「2つの SELECT の列数と型がそろっている」ことが条件です。
flowchart LR
A["UNION<br/>どちらかに含まれる<br/>(和・重複は1つに)"]
B["INTERSECT<br/>両方に含まれる<br/>(積・共通部分)"]
C["EXCEPT<br/>左にあって右にない<br/>(差)"]
UNION ― 2つの結果を1つに(重複は除去)。
SELECT id, name FROM products WHERE price >= 100000
UNION
SELECT id, name FROM products WHERE stock = 0;
重複を消さずに全部つなぎたいときは UNION ALL を使います(そのぶん速い)。
EXCEPT ― 引き算。「一度も注文していない会員」は、「全会員」から「注文したことのある会員」を引けば求まります。
SELECT id FROM users
EXCEPT
SELECT user_id FROM orders;
orders に登場する user_id は 1〜5 なので、この結果は 6(山本さん)だけ。「該当しないもの」を出すのに集合演算が効くわかりやすい例です。
INTERSECT ― 共通部分。両方の SELECT に現れる行だけを返します。
やってみよう
初期表示の UNION を実行し、高額商品(ノートPC)と在庫切れ商品(Webカメラ)が1つのリストにまとまることを確認しましょう。次に上の EXCEPT の例を実行して、「一度も注文していない会員」だけが残ることを見てください。
演習
EXCEPT を使って、一度も注文されていない商品の id を求めてください(products の全 id から、order_items に登場する product_id を引きます)。
ヒント1を見る
SELECT id FROM products から SELECT product_id FROM order_items を引きます。
ヒント2を見る
SELECT id FROM products EXCEPT SELECT product_id FROM order_items;