sql >> データベース >  >> RDS >> Mysql

MySQL-行から列へ

    この問題を解決するために実行する手順について、もう少し長く詳細な説明を追加します。長すぎる場合はお詫び申し上げます。

    私はあなたが与えたベースから始めて、それを使って、この投稿の残りの部分で使用するいくつかの用語を定義します。これがベーステーブルになります :

    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番目のステップを含む)を使用してそれに取り組みます。

    1. 目的の列、つまりy値を選択します およびx値
    2. ベーステーブルを追加の列で拡張します-x値ごとに1つ
    3. 拡張テーブルをグループ化して集約します-y値ごとに1つのグループ
    4. (オプション)集約されたテーブルをきれいにする

    これらの手順を問題に適用して、何が得られるかを見てみましょう。

    ステップ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の場合、それほど良くありません。クエリを生成するストアドプロシージャを使用したソリューションがいくつかありますが、それらは醜く、正しく理解するのが困難です。現在、ピボットテーブルに多数の列が必要な場合に、この問題を解決するための適切な方法がわかりません。


    1. 実行中のSELECTステートメントを強制終了する方法

    2. phpPgAdminからのPostgressql挿入クエリ構文エラー

    3. SQLで平均を丸めるときに小数を取得するにはどうすればよいですか?

    4. Oracle ForUserSecurityでのプロファイルの作成