MySQL で複数のテーブルから SELECT する方法
-
GROUP BY
food
を用いて複数のテーブルから SELECT する -
MySQL で複数のテーブルから SELECT するために
JOIN
を使用する -
GROUP_CONCAT()
を使って MySQL で結果を操作する
このチュートリアルでは、MySQL を使って 1つのスクリプトで複数のテーブルから SELECT
をクエリする方法を紹介します。
1つのシナリオをデモしてみましょう。
SELECT name, price, details, type, FROM food, food_order WHERE breakfast.id = 'breakfast_id'
ここでは、各 FROM
エントリに対応するテーブルのサンプルを想像してみましょう。
food
food_id | name | price | options |
---|---|---|---|
1 | Eggs | 10.00 | Scrambled, Sunny Side, Boiled |
2 | Ice cream | 30.00 | Vanilla, Strawberry, Chocolate |
3 | Ramen | 12.00 | Regular, Spicy |
food_menu
order_id | photo | food_id |
---|---|---|
1 | eggs_scrambled.jpg | 1 |
2 | eggs_sunnyside.jpg | 1 |
3 | eggs_boiled.png | 1 |
4 | icecream_vanilla.jpg | 2 |
5 | icecream_strawberry.jpg | 2 |
6 | ice_cream_chocolate.jpg | 2 |
7 | ramen_regular.jpg | 3 |
8 | ramen_spicy.jpg | 3 |
上記のテーブルをベースに、卵には 3 枚の写真があり、アイスクリームには 3 枚の写真があり、ラーメンには 2 枚の写真があることがわかります。作成する出力は、food
と food_menu
の集計表であり、すべての食品を一緒に表示します。メニューの対応する写真とそれらを組み合わせます。
これをクエリにしてみましょう。
SELECT name, price, options, photo
FROM food, food_menu
WHERE food_id = '1'
結果は次のようになります。
name | price | options | photo |
---|---|---|---|
1 | Eggs | Scrambled, Sunny Side, Boiled | eggs_sunnyside.jpg |
2 | Eggs | Scrambled, Sunny Side, Boiled | eggs_scrambled.jpg |
3 | Eggs | Scrambled, Sunny Side, Boiled | eggs_boiled.jpg |
food
に関連する food_menu
の行が複数あるため、データが重複しています。この場合、food_menu
には Eggs に直接関連する写真が 3 枚あります。
なぜなら、food_menu
のすべてのエントリはテーブル food
に関連する別のエンティティとみなされるからです。
もし、food
と food_menu
を同時に一行にまとめてクエリを実行したいのであれば、いくつかの方法があります。
GROUP BY food
を用いて複数のテーブルから SELECT する
このアプローチでは GROUP BY
を用いて両方のテーブルを一つの結果に集約します。しかし、結果が一意になるように強制しているため、food_menu
の最初のインスタンスしか取得できないという欠点があります。
以下は GROUP BY
food
テーブルに対するクエリです。
SELECT name, price, options, photo
FROM food, food_menu
WHERE food_id = '1'
GROUP BY food_id
次に、次の結果が表示されます。
name | price | options | photo |
---|---|---|---|
1 | Eggs | Scrambled, Sunny Side, Boiled | eggs_sunnyside.jpg |
これで条件は満たされましたが、写真は 1 枚しか返されません。
MySQL で複数のテーブルから SELECT するために JOIN
を使用する
このアプローチでは、SQL の JOIN
または RIGHT JOIN
コマンドを利用します。
スクリプト内に 2つの FROM 条件を持つ代わりに、外部キー food_id
に基づいて food_menu
を JOIN します。food
は f
、food_menu
は fm
とエイリアスを付けました。
SELECT f.name, f.price, f.options, fm.food_menu
FROM food AS f
JOIN food_menu AS fm ON fm.food_id = f.food_id
WHERE food_id = '1'
GROUP BY f.food_id
このメソッドは前のメソッドとは異なりますが、同じ結果が得られます。これは food_menu
の最初のインスタンスを返します。なぜなら、GROUP BY
はクエリがその条件に基づいて一意な行を返すように強制するからです。
name | price | options | photo |
---|---|---|---|
1 | Eggs | Scrambled, Sunny Side, Boiled | eggs_sunnyside.jpg |
GROUP_CONCAT()
を使って MySQL で結果を操作する
先ほどの問題の回避策は、food_menu
の結果を 1つの文字列にまとめるために GROUP_CONCAT()
を使用することで、すべてのレコードを 1 行にまとめることができます。
GROUP_CONCAT()
とは何ですか
GROUP_CONCAT
は複数の行のデータを一つのフィールドにまとめる関数です。これは GROUP BY
特殊な関数で、グループに少なくとも 1つの非 NULL 値が含まれている場合に修正された文字列を返します。それ以外の場合は NULL
を返します。
上のクエリを GROUP_CONCAT()
photo
カラムに変更して、結果を一つの文字列に連結します。
SELECT name, price, options, GROUP_CONCAT(photo, ', ')
FROM food, food_menu
WHERE food_id = '1'
GROUP BY food_id
これにより、food_menu
のフォトカラムを連結して、food
のユニークなエントリごとに 1 行だけが生成されるようにします。結果は以下のようになります。
name | price | options | photo |
---|---|---|---|
1 | Eggs | Scrambled, Sunny Side, Boiled | eggs_sunnyside.jpg,eggs_scrambled.jpg,eggs_boiled.jpg |
ご覧のように、food
テーブルの中の卵に関連する 3つの photo
カラムが連結されています。
GROUP BY
と WHERE
条件を削除すると
SELECT name, price, options, GROUP_CONCAT(photo, ', ')
FROM food, food_menu
結果は次のようになります。
name | price | options | photo |
---|---|---|---|
1 | Eggs | Scrambled, Sunny Side, Boiled | eggs_sunnyside.jpg,eggs_scrambled.jpg,eggs_boiled.jpg |
2 | Ice Cream | Vanilla, Strawberry, Chocolate | icecream_vanilla.jpg,icecream_strawberry.jpg,icecream_chocolate.jpg |
3 | Ramen | Regular, Spicy | ramen_regular.jpg,ramen_spicy.jpg |
GROUP_CONCAT()
の使用には注意してください。文字列にカンマが含まれており、CONCAT
のデリミタにもカンマが含まれている場合、列を解析するとデータが破損してしまいます。
そのため、この関数を使用する前に、デリミタが操作しているカラムに対して無効な文字であることを確認してください。
Skilled in Python, Java, Spring Boot, AngularJS, and Agile Methodologies. Strong engineering professional with a passion for development and always seeking opportunities for personal and career growth. A Technical Writer writing about comprehensive how-to articles, environment set-ups, and technical walkthroughs. Specializes in writing Python, Java, Spring, and SQL articles.
LinkedIn