この問題を解決するための手順について、もう少し長く詳細な説明を追加します。長すぎる場合はお詫び申し上げます。
私はあなたが与えたベースから始めて、この投稿の残りの部分で使用するいくつかの用語を定義するために使用します。これがベーステーブルになります。
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
これが私たちの目標、かなりのピボットテーブルになります。
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
値history.hostid
列がなろうy値ピボットテーブルに。history.itemname
列の値はx値になります(明らかな理由による)。
ピボットテーブルを作成する問題を解決する必要がある場合は、3つのステップのプロセス(オプションで4番目のステップを使用)を使用してそれに取り組みます。
- 対象の列、つまりy値とx 値を選択する
- ベーステーブルを追加の列で拡張します-各x値に 1つ
- 拡張テーブルのグループ化と集計-各y値に 1つのグループ
- (オプション)集約されたテーブルをきれいにする
これらの手順を問題に適用して、何が得られるかを見てみましょう。
ステップ1:対象の列を選択します。望ましい結果でhostid
は、y値とx 値をitemname
提供します。
手順2:追加の列でベーステーブルを拡張します。通常、x値ごとに1つの列が必要です。x値の列はitemname
次のとおりです。
create view history_extended as (
select
history.*,
case when itemname = "A" then itemvalue end as A,
case when itemname = "B" then itemvalue end as B,
case when itemname = "C" then itemvalue end as C
from history
);
select * from history_extended;
+--------+----------+-----------+------+------+------+
| hostid | itemname | itemvalue | A | B | C |
+--------+----------+-----------+------+------+------+
| 1 | A | 10 | 10 | NULL | NULL |
| 1 | B | 3 | NULL | 3 | NULL |
| 2 | A | 9 | 9 | NULL | NULL |
| 2 | C | 40 | NULL | NULL | 40 |
+--------+----------+-----------+------+------+------+
行数は変更していません。列を追加しただけです。また、パターンの注意NULL
Sを-持つ行がitemname = "A"
新しい列に対して非ヌル値を有しA
、そして他の新しい列のNULL値。
ステップ3:拡張テーブルをグループ化して集計します。group by hostid
y値を提供するため、が必要です。
create view history_itemvalue_pivot as (
select
hostid,
sum(A) as A,
sum(B) as B,
sum(C) as C
from history_extended
group by hostid
);
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | NULL |
| 2 | 9 | NULL | 40 |
+--------+------+------+------+
(これで、y値ごとに1つの行ができることに注意してください。) わかりました、もうすぐ完了です!これらの醜いNULL
s を取り除く必要があるだけです。
ステップ4:きれいにする。null値をゼロに置き換えるだけなので、結果セットが見やすくなります。
create view history_itemvalue_pivot_pretty as (
select
hostid,
coalesce(A, 0) as A,
coalesce(B, 0) as B,
coalesce(C, 0) as C
from history_itemvalue_pivot
);
select * from history_itemvalue_pivot_pretty;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
そして、これで完了です。MySQLを使用して、すてきで美しいピボットテーブルを作成しました。
この手順を適用する際の考慮事項:
- 追加の列で使用する値。
itemvalue
この例で使用しました
- 追加の列で使用する「ニュートラル」値。使用
NULL
しましたが、実際の状況に応じて、0
または""
- グループ化するときに使用する集約関数。私は使用
sum
しましたがcount
、max
頻繁に使用されています(max
多くの行全体で普及していた1行「オブジェクト」を構築する際によく使用されます)
- y値に複数の列を使用する。このソリューションは、y値に単一の列を使用することに限定されていません-余分な列を
group by
句に接続するだけです(そしてselect
それらを忘れないでください)。
既知の制限:
- このソリューションでは、ピボットテーブルにn列を使用できません。ベーステーブルを拡張するときに、各ピボット列を手動で追加する必要があります。したがって、5または10のx値の場合、このソリューションは適切です。100の場合、あまり良くありません。クエリを生成するストアドプロシージャを使用したいくつかのソリューションがありますが、それらは醜く、正しく行うのが困難です。現在、ピボットテーブルに多数の列が必要な場合に、この問題を解決する適切な方法を知りません。