この問題を解決するために実行する手順について、もう少し長く詳細な説明を追加します。長すぎる場合はお詫び申し上げます。
私はあなたが与えたベースから始めて、それを使って、この投稿の残りの部分で使用するいくつかの用語を定義します。これがベーステーブルになります :
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値を提供します およびitemname
x値を提供します 。
ステップ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以外の値があります 、および他の新しい列の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の場合、それほど良くありません。クエリを生成するストアドプロシージャを使用したソリューションがいくつかありますが、それらは醜く、正しく理解するのが困難です。現在、ピボットテーブルに多数の列が必要な場合に、この問題を解決するための適切な方法がわかりません。