━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■第34回 SQLの小技
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
前々回、前回とサブクエリを説明しました。
今回は、その応用を紹介したいと思います。
実例を通して紹介しますので、以下のサンプルテーブルをご覧ください。
・取引明細2月
---------------------------------------------
| 取引番号 | 顧客コード | 商品コード | 数量 |
-----------+------------+------------+-------
| 09020001 | 0001 | A001 | 10 |
-----------+------------+------------+-------
| 09020002 | 0001 | B001 | 5 |
-----------+------------+------------+-------
| 09020003 | 0002 | A002 | 8 |
-----------+------------+------------+-------
| 09020004 | 0003 | A001 | 25 |
-----------+------------+------------+-------
| 09020005 | 0001 | B002 | 15 |
---------------------------------------------
・取引明細3月
---------------------------------------------
| 取引番号 | 顧客コード | 商品コード | 数量 |
-----------+------------+------------+-------
| 09030001 | 0001 | A001 | 15 |
-----------+------------+------------+-------
| 09030002 | 0005 | C001 | 10 |
-----------+------------+------------+-------
| 09030003 | 0006 | B002 | 20 |
-----------+------------+------------+-------
| 09030004 | 0007 | A001 | 5 |
-----------+------------+------------+-------
| 09030005 | 0008 | A002 | 3 |
---------------------------------------------
・商品
----------------------------------
| 商品コード | 商品名 | 単価 |
-------------+------------+-------
| A001 | 抹茶ケーキ | 200 |
-------------+------------+-------
| A002 | モンブラン | 250 |
-------------+------------+-------
| B001 | クッキー | 80 |
-------------+------------+-------
| B002 | ビスケット | 70 |
-------------+------------+-------
| C001 | マシュマロ | 100 |
----------------------------------
●片方にあって、もう片方に無いデータ
2月は売れていたけど3月になったら売れなくなった商品を知りたい場合、
取引明細2月にあるが、取引明細3月に存在しない商品コードを選択すれば
よいことになります。
取引明細2月をベースにして、取引明細3月に存在する商品すべてを否定し
た以下のようなサブクエリで実現できますね。
SELECT
商品コード
FROM
取引明細2月
WHERE
商品コード NOT IN (
SELECT
商品コード
FROM
取引明細3月
)
--------------
| 商品コード |
--------------
| B001 |
--------------
また、このケースでは以下のように記述しても全く同じ結果が得られます。
SELECT
商品コード
FROM
取引明細2月
WHERE
NOT EXISTS (
SELECT *
FROM
取引明細3月
WHERE
取引明細2月.商品コード = 取引明細3月.商品コード
)
2つのSQLの違いは何でしょうか?
実は大きな違いがあるのです。
最初のSQLでは、サブクエリ結果をNOT INとしています。
INは、指定したもの全てに対し、対象であるかをチェックします。
一方、2番目のSQLでは、NOT EXISTSを使用しています。
EXISTSは存在確認の構文であり、一つでも存在するかを返すため、対象全て
をチェックはしません。
取引明細2月、取引明細3月ともに、商品コードにA001が複数存在します。
NOT EXISTSを使用すると、A001が最初に一致した段階で存在確認が終わるた
め、それ以降の組み合わせについてチェックをせず、その分早くなります。
そして、本来の目的も「2月に存在して、3月に存在しない商品を求める」
ということですので、存在確認であるEXISTS構文を使用する方が、目的と手
段が一致しているとも言えますね。
●複数のクエリ結果を結合する
取引量の多い商品を知るため、2月分・3月分の取引数量が10以上の明細を
まとめてみましょう。
例えば2月分であれば、
SELECT
*
FROM
取引明細2月
WHERE
数量 >= 10
となります。
3月分も、テーブル名が変わるだけですね。
そして、クエリ結果を結合するには、UNIONを使用します。
SELECT
*
FROM
取引明細2月
WHERE
数量 >= 10
UNION ALL
SELECT
*
FROM
取引明細3月
WHERE
数量 >= 10
---------------------------------------------
| 取引番号 | 顧客コード | 商品コード | 数量 |
-----------+------------+------------+-------
| 09020001 | 0001 | A001 | 10 |
-----------+------------+------------+-------
| 09020004 | 0003 | A001 | 25 |
-----------+------------+------------+-------
| 09020005 | 0001 | B002 | 15 |
-----------+------------+------------+-------
| 09030001 | 0001 | A001 | 15 |
-----------+------------+------------+-------
| 09030002 | 0005 | C001 | 10 |
-----------+------------+------------+-------
| 09030003 | 0006 | B002 | 20 |
---------------------------------------------
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━