MySQL の GROUP_CONCAT 関数:サブクエリとの組み合わせでデータ集計をパワーアップ
MySQL のサブクエリで GROUP_CONCAT を使用する方法
使用例
顧客の注文商品リストを取得する
SELECT
customer_name,
GROUP_CONCAT(product_name) AS products
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.id
GROUP BY customer_name;
この例では、orders
テーブルと customers
テーブルを結合し、顧客ごとに注文した商品名をカンマ区切りで連結して表示します。
各カテゴリの商品の平均価格と個数を取得する
SELECT
category_name,
AVG(product_price) AS average_price,
COUNT(*) AS product_count
FROM products
GROUP BY category_name;
この例では、products
テーブルの各カテゴリについて、商品の平均価格と個数を集計します。
サブクエリとの組み合わせ
SELECT
customer_name,
SUM(order_total) AS total_amount
FROM customers
INNER JOIN (
SELECT
customer_id,
SUM(product_price) AS order_total
FROM orders
GROUP BY customer_id
) AS orders_summary
ON customers.id = orders_summary.customer_id;
この例では、サブクエリを使用して顧客ごとの注文合計金額を算出し、それをメインクエリで顧客名と結合して表示します。
各カテゴリの商品の平均価格と個数を取得し、平均価格が高い順に並べ替える
SELECT
category_name,
average_price,
product_count
FROM (
SELECT
category_name,
AVG(product_price) AS average_price,
COUNT(*) AS product_count
FROM products
GROUP BY category_name
) AS product_summary
ORDER BY average_price DESC;
この例では、サブクエリを使用して各カテゴリの商品の平均価格と個数を集計し、それをメインクエリで平均価格が高い順に並べ替えて表示します。
ポイント
- GROUP_CONCAT 関数は、連結する列を指定する必要があります。
- サブクエリで集計した結果をメインクエリで結合するには、適切な列を結合条件として指定する必要があります。
- GROUP BY 句は、サブクエリとメインクエリどちらでも使用できます。
-- テーブル定義
CREATE TABLE customers (
id INT PRIMARY KEY,
customer_name VARCHAR(255)
);
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
product_name VARCHAR(255)
);
-- データ挿入
INSERT INTO customers (id, customer_name) VALUES
(1, '山田太郎'),
(2, '佐藤花子');
INSERT INTO orders (id, customer_id, product_name) VALUES
(1, 1, '商品A'),
(2, 1, '商品B'),
(3, 2, '商品C');
-- クエリ実行
SELECT
customer_name,
GROUP_CONCAT(product_name) AS products
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.id
GROUP BY customer_name;
-- 結果
-- customer_name | products
-- -------------- | --------
-- 山田太郎 | 商品A,商品B
-- 佐藤花子 | 商品C
-- テーブル定義
CREATE TABLE products (
id INT PRIMARY KEY,
category_name VARCHAR(255),
product_name VARCHAR(255),
product_price INT
);
-- データ挿入
INSERT INTO products (id, category_name, product_name, product_price) VALUES
(1, 'カテゴリA', '商品A', 100),
(2, 'カテゴリA', '商品B', 200),
(3, 'カテゴリB', '商品C', 300);
-- クエリ実行
SELECT
category_name,
AVG(product_price) AS average_price,
COUNT(*) AS product_count
FROM products
GROUP BY category_name;
-- 結果
-- category_name | average_price | product_count
-- -------------- | -------------- | --------------
-- カテゴリA | 150 | 2
-- カテゴリB | 300 | 1
-- テーブル定義 (上記と同じ)
-- クエリ実行
SELECT
customer_name,
SUM(order_total) AS total_amount
FROM customers
INNER JOIN (
SELECT
customer_id,
SUM(product_price) AS order_total
FROM orders
GROUP BY customer_id
) AS orders_summary
ON customers.id = orders_summary.customer_id;
-- 結果
-- customer_name | total_amount
-- -------------- | --------------
-- 山田太郎 | 300
-- 佐藤花子 | 300
-- テーブル定義 (上記と同じ)
-- クエリ実行
SELECT
category_name,
average_price,
product_count
FROM (
SELECT
category_name,
AVG(product_price) AS average_price,
COUNT(*) AS product_count
FROM products
GROUP BY category_name
) AS product_summary
ORDER BY average_price DESC;
-- 結果
-- category_name | average_price | product_count
-- -------------- | -------------- | --------------
-- カテゴリB | 300 | 1
-- カテゴリA | 150 | 2
GROUP_CONCAT を使用しない方法
サブクエリと JOIN を使用
GROUP_CONCAT の代わりに、サブクエリと JOIN を使用して複数行を結合することができます。
SELECT
customer_name,
products.product_name
FROM customers
INNER JOIN (
SELECT
customer_id,
product_name
FROM orders
) AS orders_list
ON customers.id = orders_list.customer_id;
この例では、orders
テーブルの各顧客の注文商品をサブクエリで取得し、それをメインクエリで顧客名と結合しています。
FOR EACH ステートメントを使用
MySQL 8.0 以降では、FOR EACH ステートメントを使用して、サブクエリをループ処理し、複数行を結合することができます。
SET @customer_id = 1;
SELECT
customer_name,
GROUP_CONCAT(product_name) AS products
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
WHERE orders.customer_id = @customer_id
GROUP BY customer_name;
SET @customer_id = 2;
SELECT
customer_name,
GROUP_CONCAT(product_name) AS products
FROM customers
INNER JOIN orders
ON customers.id = orders.customer_id
WHERE orders.customer_id = @customer_id
GROUP BY customer_name;
この例では、FOR EACH ステートメントを使用して、顧客 ID 1 と 2 の注文商品リストをそれぞれ取得しています。
他の集計関数を使用
GROUP_CONCAT 以外にも、複数の値を結合するために使用できる集計関数はいくつかあります。
- CONCAT_WS: カンマなどの区切り文字を指定して、複数の値を結合することができます。
- JSON_ARRAYAGG: JSON 配列形式で複数の値を結合することができます。
これらの関数は、GROUP_CONCAT よりも効率的な場合もあります。
どの方法を使用するべきか
どの方法を使用するべきかは、データの構造と処理内容によって異なります。
- GROUP_CONCAT は、複数の値をカンマ区切りで連結したい場合に適しています。
- サブクエリと JOIN は、より複雑なデータ構造を処理する場合に適しています。
- FOR EACH ステートメントは、MySQL 8.0 以降を使用している場合に有効な選択肢です。
mysql sql group-concat