Webサイト制作コースのお申し込みはこちら Webサイト制作コースのお申し込みはこちら

SQLのwith句についてまとめています。

SQLのwithをSELECT文で使うサンプル

with句を使うと、入り組んだサブクエリを単純なクエリに分解して、スッキリ記述できるというメリットがあります。

【関連記事】
SQLのWITH句で可読性アップ!再帰共通表式でサクッとSQL文を書く

with句はクエリ実行中のみ有効な一時テーブルを作ります。サブクエリ結果に名前をつけて、メインクエリで参照することができます。なお、with句を使った副問合せの定義は、共通テーブル式(CTE)と呼ばれます。

特にサブクエリを同時に2つ以上使用するような複雑なクエリで威力を発揮します。

各DBMSのSELECT文でwith句を使う例を紹介します。

Oracleのwithの構文

WITH 
  query_name ([c_alias [, c_alias]...]) AS (subquery) [search__clause] [cycle_clause]
  [, query_name ([c_alias [, c_alias]...]) AS (subquery) [search_clause] [cycle_clause]]...

参考)Oracle公式ドキュメント:SELECT

query_nameは、副問合せブロックにつける名前です。副問合せが複数存在する場合に、query_nameを指定して参照するんですね。副問合せの名前はインライン・ビューまたは一時表とし扱うことが可能です。

以下は、部署のコストをdept_costs、部署のコストの平均をavg_costと副問合せに名前をつけ、平均よりもコストが多い部署名を抽出する例です。

WITH 
   dept_costs AS (
      SELECT department_name, SUM(salary) dept_total
         FROM employees e, departments d
         WHERE e.department_id = d.department_id
      GROUP BY department_name),
   avg_cost AS (
      SELECT SUM(dept_total)/COUNT(*) avg
      FROM dept_costs)
SELECT * FROM dept_costs
   WHERE dept_total >
      (SELECT avg FROM avg_cost)
      ORDER BY department_name;

DEPARTMENT_NAME                DEPT_TOTAL
------------------------------ ----------
Sales                              304500
Shipping                           156400

SQL Serverのwithの構文

[ WITH <common_table_expression> [ ,...n ] ]  
  
<common_table_expression>::=  
    expression_name [ ( column_name [ ,...n ] ) ]  
    AS  
    ( CTE_query_definition )  

参考)WITH common_table_expression (Transact-SQL) – SQL Server | Microsoft Docs

SQL Serverはwith句で複数の副問合せの指定が可能です。副問合せごとに名前(common_table_expression)をつけ、カラム名の指定も可能です。

以下は、販売員(SalesPersonID)ごとの年間の販売注文数の合計を出力する例です。

-- Define the CTE expression name and column list.  
WITH Sales_CTE (SalesPersonID, SalesOrderID, SalesYear)  
AS  
-- Define the CTE query.  
(  
    SELECT SalesPersonID, SalesOrderID, YEAR(OrderDate) AS SalesYear  
    FROM Sales.SalesOrderHeader  
    WHERE SalesPersonID IS NOT NULL  
)  
-- Define the outer query referencing the CTE name.  
SELECT SalesPersonID, COUNT(SalesOrderID) AS TotalSales, SalesYear  
FROM Sales_CTE  
GROUP BY SalesYear, SalesPersonID  
ORDER BY SalesPersonID, SalesYear;  

MySQLのwithの構文

with_clause:
    WITH [RECURSIVE]
        cte_name [(col_name [, col_name] ...)] AS (subquery)
        [, cte_name [(col_name [, col_name] ...)] AS (subquery)] ...

共通テーブル式(副問合せブロック)には、名前がつけられます。上記の構文ではcte_nameです。複数の共通テーブル式の定義が可能で、別の共通テーブル式の参照が可能です。

以下は、table1とtable2のselect文で定義した2つの共通テーブル式cte1とcte2を結合する例です。

WITH
  cte1 AS (SELECT a, b FROM table1),
  cte2 AS (SELECT c, d FROM table2)
SELECT b, d FROM cte1 JOIN cte2
WHERE cte1.a = cte2.c;

PostgreSQLのwithの構文

WITH regional_sales AS (
        SELECT region, SUM(amount) AS total_sales
        FROM orders
        GROUP BY region
     ), top_regions AS (
        SELECT region
        FROM regional_sales
        WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
     )
SELECT region,
       product,
       SUM(quantity) AS product_units,
       SUM(amount) AS product_sales
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

参考)Postgresql公式ドキュメント:WITH問い合わせ(共通テーブル式)

上記はPostgreSQLでwithを使ったクエリの例です。サブクエリにてregional_salesとtop_regiionsという2つの共通テーブル式を定義し、地域ごとの製品と売上数量、売上金額を抽出しています。

withを使って副問合せを記述すると、複雑な問い合わせを単純なクエリに分解することができる点です。

また、withを使って再帰的問い合わせの記述も可能です。

WITH RECURSIVE included_parts(sub_part, part, quantity) AS (
    SELECT sub_part, part, quantity FROM parts WHERE part = 'our_product'
  UNION ALL
    SELECT p.sub_part, p.part, p.quantity
    FROM included_parts pr, parts p
    WHERE p.part = pr.sub_part
  )
SELECT sub_part, SUM(quantity) as total_quantity
FROM included_parts
GROUP BY sub_part

上記は部品(part)と構成部品(sub_part)を再帰的に問い合わせ、製品すべてのの部品、構成部品を抽出する例です。

SQLのwith句のまとめ

ポテパンダの一言メモ
  • with句で共通テーブル式を定義して、複雑なサブクエリを単純なクエリに分解して記述可能
  • with句では、複数の共通テーブル式を記述可能
  • with句で、再帰的問い合わせを記述できる

エンジニアになりたい人に選ばれるプログラミングスクール「ポテパンキャンプ 」

ポテパンキャンプは卒業生の多くがWebエンジニアとして活躍している実践型プログラミングスクールです。 1000名以上が受講しており、その多くが上場企業、ベンチャー企業のWebエンジニアとして活躍しています。

基礎的な学習だけで満足せず、実際にプログラミングを覚えて実践で使えるレベルまで学習したいという方に人気です。 プログラミングを学習し実践で使うには様々な要素が必要です。

それがマルっと詰まっているポテパンキャンプでプログラミングを学習してみませんか?

卒業生の多くがWebエンジニアとして活躍

卒業生の多くがWeb企業で活躍しております。
実践的なカリキュラムをこなしているからこそ現場でも戦力となっております。
活躍する卒業生のインタビューもございますので是非御覧ください。

経験豊富なエンジニア陣が直接指導

実践的なカリキュラムと経験豊富なエンジニアが直接指導にあたります。
有名企業のエンジニアも多数在籍し品質高いWebアプリケーションを作れるようサポートします。

満足度高くコスパの高いプログラミングスクール「ポテパンキャンプ」

運営する株式会社ポテパンは10,000人以上のエンジニアのキャリアサポートを行ってきております。
そのノウハウを活かして実践的なカリキュラムを随時アップデートしております。

代表の宮崎もプログラミングを覚えサイトを作りポテパンを創業しました。
本気でプログラミングを身につけたいという方にコスパ良く受講していただきたいと思っておりますので、気になる方はぜひスクール詳細をのぞいてくださいませ。