SQLを使ってデータ抽出をする際、欲しい形のデータにするために複雑な処理をしなければならないケースも多々あります。その処理において副問い合わせ(サブクエリ)を用いるケースもあると思います。
通常のサブクエリは、その処理内容が複雑になると、元のクエリ自体の可読性が下がってしまいます。そこで使えるのがWITH句を使った副問合せです。
今回はWITH句を使ったSQLの作成の流れを紹介していこうと思います。
環境・前提
DB:PostgreSQL
以下のテーブルを使います。
- payment
- customer
WITH句とは
WITH句を使うと、サブクエリに名前を付けて別管理することができます。サブクエリでの抽出内容を一時テーブルとして管理できるイメージです。
WITH句内で作成した一時テーブルは、そのクエリ内で何度でも呼び出すことができます。そのため、同一クエリ内で何度も副問合せとしてDBにアクセスする必要がなくなります。
ただしこの一時テーブルは、実行クエリ内でしか使うことができません。
クエリを書いてみる
百聞は一見に如かず。実際にWITH句を使ったクエリを書いてみましょう。上のpaymentテーブルとcustomerテーブルから顧客ごとの支払い合計を算出し、顧客名と共に取得してみようと思います。
まずSQL全体は以下のようになります。
WITH test1 AS
(
SELECT customer_id, SUM(amount) AS total_payment FROM payment
GROUP BY customer_id
)
SELECT test1.customer_id, test1.total_payment, customer.first_name
FROM test1
INNER JOIN customer
ON test1.customer_id=customer.customer_id
WHERE test1.total_payment>150
WITH句を使ってtest1を作成しています。test1はpaymentテーブルのamountをcuntomer_idごとに集計したテーブルです。test1の実行結果は以下のようになります(一部)。
下のSELECT文ではtest1の結果にcustomerテーブルのfirst_nameを結合し、さらにtotal_paymentが150以上の顧客に絞って抽出しています。実行結果は以下のようになります。
このように、WITH句を用いることで、クエリ内で一時的に作成したテーブルを利用することができるようになります。
複数の一時テーブルを作りたいとき
WITH句内で複数の一時テーブルを作成することも可能です。その場合は、以下のルールで作成します。
WITH テーブル1 AS(
--処理--
),
テーブル2 AS(
--処理--
),
テーブル3 AS(
--処理--
),...
注意点
便利なWITH句ですが、注意すべき点もあります。
WITH句で作成した一時テーブルはメモリ上で保持されることになります。そして、そのクエリのセッション中はずっと保持されます。
この特性上、データ量が膨大な一時テーブルを作成したり、一時テーブルの数が増えすぎたりしてメモリを圧迫してしまうとパフォーマンスが落ちてしまう可能性があります。
まとめ
SQLでのWITH句の使い方を紹介しました。WITH句を使うと複雑なクエリも可読性を下げることなくコーディングができるのでおすすめです。
しかし、メモリサイズも考慮して大きなデータを扱う際は注意してください。
ではでは👋