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

2つの列に基づいて行を列に動的に変換するMysqlクエリ

    両方のorderの値の数がわかっている場合 およびitem 、次にクエリを次のようにハードコーディングできます:

    select id,
      max(case when `order` = 1 then data end) order1,
      max(case when `order` = 2 then data end) order2,
      max(case when `order` = 3 then data end) order3,
      max(case when item = 1 then price end) item1,
      max(case when item = 2 then price end) item2,
      max(case when item = 3 then price end) item3,
      max(case when item = 4 then price end) item4
    from tableA
    group by id;
    

    デモ を参照してください。 。しかし、発生する問題の一部は、データの複数の列を変換しようとしているためです。最終結果を取得するための私の提案は、最初にデータのピボットを解除することです。 MySQLにはピボット解除機能はありませんが、UNION ALLを使用して、列の複数のペアを行に変換できます。ピボットを解除するコードは次のようになります:

    select id, concat('order', `order`) col,  data value
    from tableA
    union all
    select id, concat('item', item) col, price value
    from tableA;
    

    デモ を参照してください。 。この結果は次のようになります:

    | ID |    COL | VALUE |
    -----------------------
    |  1 | order1 |     P |
    |  1 | order1 |     P |
    |  1 | order1 |     P |
    |  1 |  item1 |    50 |
    |  1 |  item2 |    60 |
    |  1 |  item3 |    70 |
    

    ご覧のとおり、これは orderの複数の列を取得しています /データ およびitem /価格 そしてそれを複数の行に変換します。それが完了したら、CASEを使用した集計関数を使用して値を列に戻すことができます:

    select id, 
      max(case when col = 'order1' then value end) order1,
      max(case when col = 'order2' then value end) order2,
      max(case when col = 'order3' then value end) order3,
      max(case when col = 'item1' then value end) item1,
      max(case when col = 'item2' then value end) item2,
      max(case when col = 'item3' then value end) item3
    from
    (
      select id, concat('order', `order`) col,  data value
      from tableA
      union all
      select id, concat('item', item) col, price value
      from tableA
    ) d
    group by id;
    

    デモ を参照してください。 。最後に、上記のコードを動的なプリペアドステートメントクエリに変換する必要があります。

    SET @sql = NULL;
    SELECT
      GROUP_CONCAT(DISTINCT
        CONCAT(
          'max(case when col = ''',
          col,
          ''' then value end) as `', 
          col, '`')
      ) INTO @sql
    FROM
    (
      select concat('order', `order`) col
      from tableA
      union all
      select concat('item', `item`) col
      from tableA
    )d;
    
    SET @sql = CONCAT('SELECT id, ', @sql, ' 
                      from
                      (
                        select id, concat(''order'', `order`) col,  data value
                        from tableA
                        union all
                        select id, concat(''item'', item) col, price value
                        from tableA
                      ) d
                      group by id');
    
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    

    SQL Fiddle withdemo を参照してください。 。これにより、結果が得られます:

    | ID | ORDER1 | ORDER2 | ORDER3 | ITEM1 | ITEM2 |  ITEM3 |  ITEM4 |
    -------------------------------------------------------------------
    |  1 |      P |      Q | (null) |    50 |    60 |     70 | (null) |
    |  2 |      P | (null) |      S |    50 |    60 | (null) |     80 |
    



    1. PostgreSQL13でのUnicode正規化

    2. UTF-8文字エンコードの戦いjson_encode()

    3. Oracleデータベースのテーブルドロップ列を変更する

    4. PL/pgSQLでinteger[]を反復処理