MySQLクエリ結果で列の値を列名として設定する方法(CASE文によるピボット変換)
MySQLクエリ結果で列の値を列名として設定する方法
MySQLのクエリ結果において、列に格納された値そのものを列名(見出し)として表示したいケースがあります。これは「縦持ちデータ」を「横持ちデータ」へ変換する、いわゆるピボット(クロス集計)処理と呼ばれる手法です。SQL ServerなどにあるPIVOT句はMySQLには存在しないため、代わりにCASE文と集計関数を組み合わせて実現します。
基本構文
以下が基本的な書き方です。CASE文で条件に一致する行だけ対象の値を返し、MAX関数でNULL以外の値を集約することで、1行1列の形式に変換します。
select yourIdColumnName, max(case when (yourColumnName1='yourValue1') then yourColumnName2 else NULL end) as 'yourValue1', max(case when (yourColumnName1='yourValue2') then yourColumnName2 else NULL end) as 'yourValue2', max(case when (yourColumnName1='yourValue3') then yourColumnName2 else NULL end) as 'yourValue3', . . N from valueAsColumn group by yourIdColumnName order by yourIdColumnName;
動作確認用テーブルの作成
それでは実際に構文を理解するため、サンプルテーブルを作成してみましょう。テーブル作成のクエリは次のとおりです。
mysql> create table valueAsColumn
-> (
-> UserId int,
-> UserColumn1 varchar(10),
-> UserColumn2 varchar(10)
-> );
Query OK, 0 rows affected (0.75 sec)
テストデータの挿入
続いて、INSERTコマンドでいくつかのレコードを登録します。
mysql> insert into valueAsColumn values(0,'John','A+'); Query OK, 1 row affected (0.18 sec) mysql> insert into valueAsColumn values(0,'Carol','B'); Query OK, 1 row affected (0.17 sec) mysql> insert into valueAsColumn values(0,'Sam','C'); Query OK, 1 row affected (0.17 sec) mysql> insert into valueAsColumn values(1,'John','D'); Query OK, 1 row affected (0.20 sec) mysql> insert into valueAsColumn values(1,'Carol','A'); Query OK, 1 row affected (0.20 sec) mysql> insert into valueAsColumn values(1,'Carol','C'); Query OK, 1 row affected (0.15 sec)
SELECT文ですべてのレコードを確認します。
mysql> select *from valueAsColumn;
実行結果は以下のとおりです。
+--------+-------------+-------------+ | UserId | UserColumn1 | UserColumn2 | +--------+-------------+-------------+ | 0 | John | A+ | | 0 | Carol | B | | 0 | Sam | C | | 1 | John | D | | 1 | Carol | A | | 1 | Carol | C | +--------+-------------+-------------+ 6 rows in set (0.00 sec)
列の値を列名として表示するクエリ
ここからが本題です。UserColumn1の各値(John・Carol・Sam)を列名に変換して表示するクエリは以下のとおりです。
mysql> select UserId,
-> max(case when (UserColumn1='John') then UserColumn2 else NULL end) as 'John',
-> max(case when (UserColumn1='Carol') then UserColumn2 else NULL end) as 'Carol',
-> max(case when (UserColumn1='Sam') then UserColumn2 else NULL end) as 'Sam'
-> from valueAsColumn
-> group by UserId
-> order by UserId;
実行結果は以下のとおりです。
+--------+------+-------+------+ | UserId | John | Carol | Sam | +--------+------+-------+------+ | 0 | A+ | B | C | | 1 | D | C | NULL | +--------+------+-------+------+ 2 rows in set (0.00 sec)
仕組みの解説
このクエリが機能する仕組みを簡単に整理します。
- CASE文:各行について「UserColumn1が指定した値(例:'John')と一致すればUserColumn2の値を返し、一致しなければNULLを返す」という判定を行います。
- MAX関数:GROUP BYでUserIdごとにまとめた際、NULLは無視されるため、条件に一致した値のみが残ります。
- GROUP BY:同じUserIdの複数行を1行に集約し、それぞれの値を別々の列として並べます。
上記の結果を見ると、UserId=1の「Sam」には該当データが存在しないためNULLが表示されています。このようにCASE文を組み合わせることで、柔軟なクロス集計を実現できます。なお、列名が事前に不明な場合は、ストアドプロシージャやプリペア드ステートメントを使って動的にSQLを生成する方法も検討するとよいでしょう。
-
MySQLで行の値を合計して結果を並べ替えるクエリの書き方
MySQLで行の値を合計し、結果を並べ替える方法テーブル内の同じキーを持つ行の値を合計し、その結果を並べ替えたい場合には、GROUP BY句とORDER BY句を組み合わせて使用します。GROUP BYで対象の列ごとにデータをグループ化し、SUM関数で合計値を算出した後、ORDER BYで並べ替えるという流れになります。ここでは、生徒名と点数が登録されたテーブルを例に、生徒ごとの合計点を降順で取得する手順を解説します。1. サンプルテーブルを作成するまず、CREATE TABLE文でテーブルを作成します。mysql> create table DemoTable1499 &nb
-
MySQLクエリで列名にエイリアス(別名)を設定する方法
MySQLでは、SELECT文を使って列名に「エイリアス(別名)」を設定できます。エイリアスを利用すると、出力結果の見出しをわかりやすい名前に変更でき、レポート作成やアプリケーションでのデータ表示が格段に読みやすくなります。列名にエイリアスを設定する基本構文SELECT yourColumnName1 anyAliasName1, yourColumnName2 anyAliasName2FROM yourTableName anyAliasName;このように、列名の後にスペースを空けて任意の別名を記述するだけで、その列の表示名がエイリアスに置き換わります。テーブル名にも同様にエイリアスを設