【保存版】GROUP_CONCAT関数を超えた!MySQLで複数行をカンマ区切りにする4つの方法

2024-07-02

MySQLで複数の行をカンマ区切り単一行として取得する方法

GROUP_CONCAT関数 は、SELECTクエリ内で指定した列の値をカンマ区切りで連結し、1つの文字列として返す関数です。

基本的な構文

SELECT GROUP_CONCAT(DISTINCT 列名) AS 列名_alias
FROM テーブル名
[WHERE 条件]
[GROUP BY グループ化列];

下記のテーブル articles があり、各記事に紐づくキーワードをカンマ区切りで1行に取得したい場合を例として説明します。

CREATE TABLE articles (
  article_id INT PRIMARY KEY,
  title VARCHAR(255),
  keyword VARCHAR(255)
);

INSERT INTO articles (article_id, title, keyword) VALUES
(1, 'MySQL入門', 'データベース', 'SQL'),
(2, 'Webサイト構築', 'HTML', 'CSS', 'JavaScript'),
(3, '機械学習の基礎', '人工知能', 'データ分析'),
(1, 'MySQL応用例', 'トランザクション', 'ロック');

この場合、以下のクエリで各記事IDと、それに紐づくキーワードをカンマ区切りで1行ずつ取得できます。

SELECT article_id, GROUP_CONCAT(DISTINCT keyword) AS keywords
FROM articles
GROUP BY article_id;

結果

article_id | keywords
--------- | --------
1          | データベース, SQL, トランザクション
2          | HTML, CSS, JavaScript
3          | 人工知能, データ分析

補足

  • DISTINCT キーワードを省略すると、重複するキーワードもカンマ区切りで連結されます。
  • ORDER BY 句を使用して、キーワードの並び順を指定することができます。
  • GROUP BY 句を省略すると、すべての行が1つのカンマ区切り文字列に連結されます。



CREATE TABLE books (
  book_id INT PRIMARY KEY,
  title VARCHAR(255),
  author VARCHAR(255)
);

INSERT INTO books (book_id, title, author) VALUES
(1, 'ハリー・ポッターと賢者の石', 'J.K.ローリング'),
(2, 'ハリー・ポッターと秘密の部屋', 'J.K.ローリング'),
(3, 'ハリー・ポッターとアズカバンの囚徒', 'J.K.ローリング'),
(4, '君の名は。', '新海誠'),
(5, '天気の子', '新海誠');
SELECT book_id, GROUP_CONCAT(DISTINCT author) AS authors
FROM books
GROUP BY book_id;
book_id | authors
--------- | --------
1          | J.K.ローリング
2          | J.K.ローリング
3          | J.K.ローリング
4          | 新海誠
5          | 新海誠

このサンプルコードでは、以下の点に注目してください。

  • books テーブルには、書籍ID、タイトル、著者名の3つの列があります。
  • GROUP_CONCAT関数 を使用して、author 列の値をカンマ区切りで連結しています。
  • DISTINCT キーワードを使用しているので、重複する著者名は連結されません。
  • GROUP BY book_id 句を使用しているので、書籍IDごとに著者名をまとめることができます。



MySQLで複数の行をカンマ区切り単一行として取得するその他の方法

サブクエリを使用する

SELECT article_id,
       (
           SELECT GROUP_CONCAT(keyword)
           FROM articles AS a2
           WHERE a2.article_id = a1.article_id
       ) AS keywords
FROM articles AS a1;

FOR LOOPを使用する

SELECT article_id,
       (
           SELECT GROUP_CONCAT(keyword SEPARATOR ',')
           FROM (
               SELECT keyword
               FROM articles AS a2
               WHERE a2.article_id = a1.article_id
           ) AS sub
       ) AS keywords
FROM articles AS a1;

Window関数を使用する

SELECT article_id,
       STRING_AGG(keyword, ',') OVER (PARTITION BY article_id) AS keywords
FROM articles;

それぞれの方法のメリットとデメリット

方法メリットデメリット
GROUP_CONCAT関数シンプルでわかりやすいサブクエリを使用するため、複雑なクエリになると見にくくなる可能性がある
サブクエリ柔軟性が高い複数のクエリを結合するため、処理速度が遅くなる可能性がある
FOR LOOP可読性が高いコードが冗長になる可能性がある
Window関数最新のMySQLバージョンでのみ使用可能他の方法に比べて知名度が低い
  • シンプルでわかりやすい方法を求める場合は、GROUP_CONCAT関数 がおすすめです。
  • 柔軟性が必要な場合は、サブクエリ を使用する方法がおすすめです。
  • 可読性を重視する場合は、FOR LOOP を使用する方法がおすすめです。
  • 最新のMySQLバージョンを使用している場合は、Window関数 を使用する方法も検討できます。

    MySQLで複数の行をカンマ区切り単一行として取得するには、GROUP_CONCAT関数 をはじめ、様々な方法があります。それぞれの方法のメリットとデメリットを理解した上で、状況に応じて適切な方法を選択しましょう。


    mysql database


    ORDER BY RAND() を使ってランダムサンプルを取得する

    概要ORDER BY RAND() を使用すると、ランダムな順序でレコードを取得できます。例このクエリは、テーブル名 テーブルからランダムに1レコードを取得します。注意点ORDER BY RAND() は、テーブル内のすべてのレコードをスキャンするため、大規模なテーブルの場合、パフォーマンスが低下する可能性があります。...


    MySQL show statusコマンドでアクティブな接続数と最大接続数を取得する

    MySQL show statusコマンドは、MySQLサーバーの状態に関する情報を表示します。このコマンドには、接続に関する多くのオプションがあります。active connectionsオプション: Threads_connected説明: 現在の接続数...


    【完全ガイド】MySQLのテーブル操作:存在確認、削除、作成、更新

    テーブルが存在する場合は削除するこの処理は、テーブルの構造を変更する場合や、古いデータを削除して新しいテーブルを作成する場合などに使用されます。以下のコードは、上記の処理をどのように実行するかを示しています。このコードは、以下の手順で実行されます。...


    Cassandra レコードの有効期限を制御: TTL の更新方法

    最も一般的な方法は、UPDATE ステートメントを使用して、TTL 値を含む新しいレコード値を既存のレコードに挿入することです。構文は以下の通りです。例:この例では、my_table テーブルの id が my-id であるレコードの value 列を updated_value に更新し、TTL を 1 時間 (3600 秒) に設定します。...


    画像保存のベストプラクティス:データベースとファイルシステムの賢い使い分け

    データベース と ファイルシステム の主な違いは以下の通りです。データベース利点:メタデータの管理に優れている: 画像に関する情報(例:名前、説明、撮影日時)を効率的に格納・検索できる。トランザクション処理に適している: 画像の更新や削除を原子的に行うことができ、データ整合性を保ちやすい。関係性の構築に適している: 画像と他の関連データ(例:商品情報、ユーザー情報)を関連付けて管理できる。...