MySQLでGROUP_CONCAT()とDISTINCTを使って、カテゴリーごとの重複商品名を連結する方法
MySQLにおけるGROUP_CONCAT()とDISTINCTの組み合わせ
GROUP_CONCAT()とDISTINCTを組み合わせることで、グループ内の重複する値を除去した上で連結することができます。
使用例
SELECT
category,
GROUP_CONCAT(DISTINCT product_name) AS products
FROM products
GROUP BY category;
この例では、products
テーブルから、category
と、category
ごとに重複する値を除去したproduct_name
の連結を取得します。
結果例
| category | products |
|----------|-----------------------------------|
| 食品 | リンゴ, バナナ, オレンジ, ブドウ |
| 家電 | テレビ, 冷蔵庫, 洗濯機, 掃除機 |
| 衣類 | シャツ, ズボン, スカート, ワンピース |
DISTINCTの注意点
DISTINCTは、GROUP_CONCAT()内の列に対してのみ適用されます。GROUP BYする列に対しては適用されません。
例:誤った使い方
SELECT
DISTINCT category,
GROUP_CONCAT(product_name) AS products
FROM products
GROUP BY category;
この例では、DISTINCTはcategory
に対して適用されますが、GROUP_CONCAT()内のproduct_nameには適用されません。
| category | products |
|----------|-----------------------------------|
| 食品 | リンゴ, バナナ, オレンジ, ブドウ, リンゴ |
| 家電 | テレビ, 冷蔵庫, 洗濯機, 掃除機, テレビ |
| 衣類 | シャツ, ズボン, スカート, ワンピース, シャツ |
正しい使い方
SELECT
category,
GROUP_CONCAT(DISTINCT product_name) AS products
FROM products
GROUP BY category;
| category | products |
|----------|-----------------------------------|
| 食品 | リンゴ, バナナ, オレンジ, ブドウ |
| 家電 | テレビ, 冷蔵庫, 洗濯機, 掃除機 |
| 衣類 | シャツ, ズボン, スカート, ワンピース |
- GROUP_CONCAT()には、
SEPARATOR
オプションを使用して、連結文字列の区切り文字を指定することができます。
詳細は、MySQLのドキュメントを参照してください。
-- テーブル作成
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
category VARCHAR(255) NOT NULL,
product_name VARCHAR(255) NOT NULL
);
-- データ挿入
INSERT INTO products (category, product_name) VALUES
('食品', 'リンゴ'),
('食品', 'バナナ'),
('食品', 'オレンジ'),
('食品', 'ブドウ'),
('食品', 'リンゴ'),
('家電', 'テレビ'),
('家電', '冷蔵庫'),
('家電', '洗濯機'),
('家電', '掃除機'),
('家電', 'テレビ'),
('衣類', 'シャツ'),
('衣類', 'ズボン'),
('衣類', 'スカート'),
('衣類', 'ワンピース'),
('衣類', 'シャツ');
-- クエリ実行
SELECT
category,
GROUP_CONCAT(DISTINCT product_name) AS products
FROM products
GROUP BY category;
| category | products |
|----------|-----------------------------------|
| 食品 | リンゴ, バナナ, オレンジ, ブドウ |
| 家電 | テレビ, 冷蔵庫, 洗濯機, 掃除機 |
| 衣類 | シャツ, ズボン, スカート, ワンピース |
その他のサンプル
SEPARATOR
オプションを使用して、連結文字列の区切り文字を指定する
SELECT
category,
GROUP_CONCAT(DISTINCT product_name SEPARATOR ', ') AS products
FROM products
GROUP BY category;
| category | products |
|----------|-----------------------------------|
| 食品 | リンゴ, バナナ, オレンジ, ブドウ |
| 家電 | テレビ, 冷蔵庫, 洗濯機, 掃除機 |
| 衣類 | シャツ, ズボン, スカート, ワンピース |
ORDER BY
オプションを使用して、連結する値の順序を指定する
SELECT
category,
GROUP_CONCAT(DISTINCT product_name ORDER BY product_name ASC) AS products
FROM products
GROUP BY category;
| category | products |
|----------|-----------------------------------|
| 食品 | バナナ, ブドウ, リンゴ, オレンジ |
| 家電 | 掃除機, 洗濯機, 冷蔵庫, テレビ |
| 衣類 | ワンピース, スカート, ズボン, シャツ |
サンプルコードを参考に、さまざまな方法でGROUP_CONCAT()とDISTINCTを組み合わせてみてください。
GROUP_CONCAT()とDISTINCTを組み合わせるその他の方法
サブクエリを使用する
SELECT
category,
(
SELECT GROUP_CONCAT(DISTINCT product_name)
FROM products
WHERE category = p.category
) AS products
FROM products AS p
GROUP BY category;
この方法は、サブクエリを使用して、各グループ内の重複する値を除去した上で連結します。
GROUP BY句でDISTINCTを使用する
SELECT
category,
GROUP_CONCAT(product_name) AS products
FROM (
SELECT DISTINCT category, product_name
FROM products
) AS t
GROUP BY category;
この方法は、GROUP BY句でDISTINCTを使用して、重複するレコードを事前に除去してからGROUP_CONCAT()を使用します。
ユーザー定義関数を使用する
DELIMITER //
CREATE FUNCTION group_concat_distinct(
column_name VARCHAR(255)
) RETURNS VARCHAR(255)
DETERMINISTIC
BEGIN
DECLARE result VARCHAR(255);
DECLARE values VARCHAR(255);
DECLARE cursor CURSOR FOR
SELECT DISTINCT column_name
FROM products;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET result = '';
OPEN cursor;
REPEAT
FETCH cursor INTO values;
SET result = CONCAT(result, values, ', ');
UNTIL NOT FOUND;
CLOSE cursor;
RETURN LEFT(result, LENGTH(result) - 2);
END;
//
DELIMITER ;
SELECT
category,
group_concat_distinct(product_name) AS products
FROM products
GROUP BY category;
この方法は、ユーザー定義関数を使用して、GROUP_CONCAT()とDISTINCTの機能を組み込みます。
GROUP_CONCAT()とDISTINCTを組み合わせる方法は、いくつかあります。
それぞれの特徴を理解して、目的に合った方法を選択してください。
mysql group-concat