ITサポート

セミナー

会員特典

その他

過去のコラム等

Twitter

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ■第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 |  --------------------------------------------- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━