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

1つのSQL文の中に、重複するサブクエリが何度も登場すると可読性を下げる原因となります。そこで積極的に使用したいのがSQLのWITH句。MySQLでも8.0で使用できるようになり、知名度を一気に上げました。

今回の記事ではSQLのWITH句とは何かについて詳しく解説をしつつ、SQLのWITH句を使ったハンズオンを実施していきます。

本記事の要点
  • SQL WITH句は、再帰共通表式を作るもの
  • 再起共通表式とは、式の中で何度も呼び出せる即席テーブルのこと
  • WITH句を使ってハンズオンを体験してみる

SQLのWITH句とは?

SQLのWITH句とは、1つのSQL文の中で共通した表式(テーブル)を簡略的に呼び出すことができる句のことです。そのため、SQLのWITH句で呼び出したテーブルのことを再帰共通表式(テーブル)と呼びます。

言葉だけではイメージがしづらいかと思うので、実際にSQLのWITH句を使用した例を見てみましょう。

前提として、以下のようなテーブルがあるとします。

+--------+-------+
| name   | price |
+--------+-------+
| Banana | 100   |
| Apple  | 200   |
+--------+-------+

このテーブルの中から、nameカラムだけを取り出した再帰共通表式をWITH句を使って生成して見ましょう。

mysql> WITH food_name AS ( SELECT name from foods) SELECT * FROM food_name;

以下が出力結果です。

+--------+
| name   |
+--------+
| Banana |
| Apple  |
+--------+

foodsテーブルからnameカラムだけを取り出した「food_name」という再帰共通表式を作成することができました。WITH句から始めるSQL文において「food_name」という再帰共通表式は何度でも使用することができます。そのためサブクエリ(副問い合わせ)を使用して、何度も同じテーブル呼び出しをしなくてよく、可読性が高まるというわけです。

ポテパンダの一言メモ

上記の例ではWITH句の利便性を十分に感じられなかったかもしれません。次にご紹介する例では実際にWITH句の効果を感じられるようなハンズオンをご紹介していきますので、手を動かしながら体験して見ましょう。

SQLのWITH句を使ってみよう

では、実際にSQLのWITH句を使っていきましょう。

ポテパンダの一言メモ

こちらではMySQLというデータベースを使用していきます。MySQLではバージョン8.0からWITH句が導入されていますので、バージョンを確認してからハンズオンに入っていきましょう。

準備

まずはMySQLを使用するための準備をしていきます。

MySQLのインストール・接続

まだMySQLをインストールしていない場合は、インストールしましょう。

$ brew install mysql

MySQLのインストールが終了したら、接続します。

$ sudo mysql -u root -p

データベースの作成

次にデータベースをMySQL上に作成し、使用するデータベースを指定しましょう。

mysql> CREATE DATABASE potepan;
Query OK, 1 row affected (0.00 sec)

mysql> USE potepan;

これでMySQLを使用する準備は完了しました。

テーブルの作成

まずは状態テーブル・商品テーブルの2つを作成します。状態テーブルの「状態」1の時は「賞味期限前」、2の時は「賞味期限切れ」という形で商品を管理していきます。

そして商品コードごとに、賞味期限切れの商品数と賞味期限前の商品数を月ごとに表示していきましょう。

mysql> CREATE TABLE 状態(商品_No INT, 賞味期限_年 INT, 賞味期限_月 INT, 状態 INT);
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE 商品(商品_No INT, 商品_コード INT);
Query OK, 0 rows affected (0.01 sec)

以下が作成されたテーブルです。

状態テーブル

+------------------+---------+------+-----+---------+-------+
| Field            | Type    | Null | Key | Default | Extra |
+------------------+---------+------+-----+---------+-------+
| 商品_No          | int(11) | YES  |     | NULL    |       |
| 賞味期限_年      | int(11) | YES  |     | NULL    |       |
| 賞味期限_月      | int(11) | YES  |     | NULL    |       |
| 状態             | int(11) | YES  |     | NULL    |       |
+------------------+---------+------+-----+---------+-------+

商品テーブル

+------------------+---------+------+-----+---------+-------+
| Field            | Type    | Null | Key | Default | Extra |
+------------------+---------+------+-----+---------+-------+
| 商品_No          | int(11) | YES  |     | NULL    |       |
| 商品_コード      | int(11) | YES  |     | NULL    |       |
+------------------+---------+------+-----+---------+-------+

レコードの作成

テーブルにレコードを挿入していきましょう。

mysql> INSERT INTO 状態 VALUES(0001, 2019, 12, 1),(0002, 2018, 9, 2),(0003, 2012, 5, 2);
Query OK, 3 rows affected (0.01 sec)
mysql> INSERT INTO 商品 VALUES(0001, 221590), (0002, 221590), (0003, 981224);
Query OK, 3 rows affected (0.00 sec)

これでテーブルは以下の状態になりました。

状態テーブル

mysql> SELECT * FROM 状態;
+-----------+------------------+------------------+--------+
| 商品_No   | 賞味期限_年      | 賞味期限_月      | 状態   |
+-----------+------------------+------------------+--------+
|         1 |             2019 |               12 |      1 |
|         2 |             2018 |                9 |      2 |
|         3 |             2012 |                5 |      2 |
+-----------+------------------+------------------+--------+

商品テーブル

mysql> SELECT * FROM 商品;
+-----------+------------------+
| 商品_No   | 商品_コード      |
+-----------+------------------+
|         1 |           221590 |
|         2 |           221590 |
|         3 |           981224 |
+-----------+------------------+
WITH check_table AS (
    SELECT 
        商品.商品_コード, 
        状態.賞味期限_年, 
        状態.賞味期限_月, 
        状態.状態 
            FROM 
                状態 INNER JOIN 商品 ON 状態.商品_No = 商品.商品_No), 
                SHOUHIN AS ( 
                    SELECT check_table.商品_コード, 
                    check_table.賞味期限_年, 
                    check_table.賞味期限_月, 
                    COUNT(*) cnt 
                        FROM 
                            check_table 
                        GROUP BY 
                            check_table.商品_コード, 
                            check_table.賞味期限_年, 
                            check_table.賞味期限_月), 
                        KIGEN_MAE AS ( 
                            SELECT check_table.商品_コード, 
                            check_table.賞味期限_年, 
                            check_table.賞味期限_月, 
                            COUNT(*) cnt 
                                FROM check_table 
                                WHERE 
                                    check_table.状態 = 1 
                                    GROUP BY 
                                    check_table.商品_コード, 
                                    check_table.賞味期限_年, 
                                    check_table.賞味期限_月), 
                                KIGEN_GO AS( 
                                    SELECT check_table.商品_コード, 
                                    check_table.賞味期限_年, 
                                    check_table.賞味期限_月, COUNT(*) cnt 
                                    FROM check_table 
                                        WHERE check_table.状態 = 2 
                                    GROUP BY 
                                        check_table.商品_コード, 
                                        check_table.賞味期限_年, 
                                        check_table.賞味期限_月) 
                                    SELECT SHOUHIN.商品_コード, 
                                    SHOUHIN.賞味期限_年, SHOUHIN.賞味期限_月, 
                                    SHOUHIN.cnt 商品数 
                                        FROM SHOUHIN LEFT JOIN 
                                    KIGEN_MAE ON 
                                        SHOUHIN.商品_コード = KIGEN_MAE.商品_コード AND 
                                        SHOUHIN.賞味期限_年 = KIGEN_MAE.賞味期限_年 AND 
                                        SHOUHIN.賞味期限_月 = KIGEN_MAE.賞味期限_月 
                                            LEFT JOIN 
                                    KIGEN_GO ON 
                                        SHOUHIN.商品_コード = KIGEN_GO.商品_コード AND 
                                        SHOUHIN.賞味期限_年 = KIGEN_GO.賞味期限_年 AND 
                                        SHOUHIN.賞味期限_月 = KIGEN_GO.賞味期限_月;

非常に長いですが、ポイントとして最初にWITH句で生成したcheck_tableがその後、何度も呼び出されているという点に注目しましょう。WITH句を使うと、サブクエリを入力しなくても再帰的に共通テーブルが呼び出せるというわけです。

まとめ

今回の記事ではSQLのWITH句とは何かについて詳しく解説をしつつ、SQLのWITH句を使ったハンズオンを実施していきました。

同じテーブルを何度も呼び出さなければならない場合、サブクエリを使用するよりも、1度呼び出せば何度も共通表式として呼び出せるWITH句がおすすめです。積極的にSQL文の中で使用し、可読性の高い式を記述できるようにしましょう。

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

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

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

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

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

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

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

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

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

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

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