レコードが存在するかを条件として抽出するEXISTSの使い方

とあるサブクエリで抽出した条件にマッチするかどうかを抽出することができるEXISTS演算子の使い方について説明していきます。

通常SQLで抽出するにはWHERE区での条件指定を行います。また「○○が10件以上存在するデータ」のようにHAVINGを使った複雑な抽出条件の場合は、サブクエリとIN演算子を使って抽出する方法がありますが対象データが大量の場合はクエリの実行速度のパフォーマンスが遅かったりします。

そんな複雑な条件でデータを抽出したい場合は、EXISTS演算子を使いこなすことができればより速度を速く短いSQL文でデータを抽出することができます。

今回EXISTSを説明するにあたって下記のテーブル、データが存在するものとして進めていきます。

サンプルデータ

データ構造


顧客(customer)テーブル

顧客コード(code)名前(full_name)電話番号(tel)都道府県(prefecture)
C0001佐藤 太郎090-0000-1111東京都
C0002山田 次郎090-0000-2222福岡県
C0003鈴木 三郎090-0000-3333大阪府
C0004斉藤 四郎090-0000-1111北海道
C0005渡辺 五郎090-0000-5555長崎県

商品(product)テーブル

商品コード(code)商品名(name)価格(price)
P0001商品A1000
P0002商品B500
P0003商品C800
P0004商品D900

販売(sales_order)テーブル

注文番号(code)顧客コード
(customer_code)
商品コード
(product_code)
価格
(price)
数量
(quantity)
合計金額
(total_price)
SO0001C0001P0001100011000
SO0002C0002P000250042000
SO0003C0001P000380021600

重複した電話番号を持つレコードの全列データを抽出(EXISTS)

SQL

SELECT
  C1.*
FROM
  customer AS C1
WHERE
  EXISTS(
    SELECT 
      C2.tel
    FROM 
      customer AS C2
    WHERE
      C1.tel = C2.tel
    GROUP BY
      C2.tel
    HAVING
      COUNT(C2.tel) > 1
  )
ORDER BY C1.CODE ASC

クエリ実行結果

重複した電話番号を持たないレコードの全列データを抽出(NOT EXISTS)

重複した番号を持たないデータを抽出する場合は①の逆の条件指定をすればいいので「EXISTS」を「NOT EXISTS」にするだけで抽出することができます

SQL

SELECT
  C1.*
FROM
  customer AS C1
WHERE
  NOT EXISTS(
    SELECT 
      C2.tel
    FROM 
      customer AS C2
    WHERE
      C1.tel = C2.tel
    GROUP BY
      C2.tel
    HAVING
      COUNT(C2.tel) > 1
  )
ORDER BY C1.CODE ASC

クエリ実行結果

購入履歴がある顧客データを抽出(EXISTS)

SQL

SELECT
  C.*
FROM
  customer AS C
WHERE
  EXISTS(
    SELECT 
      *
    FROM 
      sales_order AS S
    WHERE
      S.customer_code = C.code
  )
ORDER BY C.CODE ASC

クエリ実行結果

Leave a Reply

Your email address will not be published. Required fields are marked *