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

mysqlピボットテーブルの問題

    動的または不明な値をピボットしようとする場合は、最初に静的バージョンまたはハードコードされたバージョンのクエリから始めて、それを動的SQLに変換することを常にお勧めします。

    MySQLにはPIVOT関数がないため、結果を取得するには、CASE式で集計関数を使用する必要があります。コードの静的バージョンは次のようになります:

    select t.id teamid, 
      t.name teamname, 
      p.id processid, 
      p.name processname,
      max(case when pd.keyname = 'shape' then tpd.value end) shape,
      max(case when pd.keyname = 'vegetable' then tpd.value end) vegetable,
      max(case when pd.keyname = 'fruit' then tpd.value end) fruit,
      max(case when pd.keyname = 'animal' then tpd.value end) animal
    from teams t
    inner join teamprocesses tp
      on t.id = tp.teamid
    inner join TeamProcessDetails tpd
      on tp.id = tpd.teamProcessId
    inner join processes p
      on tp.processid = p.id
    inner join processdetails pd
      on p.id = pd.processid
      and tpd.processDetailsid = pd.id
    group by t.id, t.name, p.id, p.name;
    

    SQL Fiddle withDemo を参照してください。 。

    ここで、不明な数のkeynamesがある場合 列に変換する場合は、準備されたステートメント 動的SQLを生成します。コードは次のようになります:

    SET @sql = NULL;
    SELECT
      GROUP_CONCAT(DISTINCT
        CONCAT(
          'max(case when pd.keyname = ''',
          keyname,
          ''' then tpd.value end) AS ',
          replace(keyname, ' ', '')
        )
      ) INTO @sql
    from ProcessDetails;
    
    SET @sql 
        = CONCAT('SELECT t.id teamid, 
                    t.name teamname, 
                    p.id processid, 
                    p.name processname, ', @sql, ' 
                  from teams t
                  inner join teamprocesses tp
                    on t.id = tp.teamid
                  inner join TeamProcessDetails tpd
                    on tp.id = tpd.teamProcessId
                  inner join processes p
                    on tp.processid = p.id
                  inner join processdetails pd
                    on p.id = pd.processid
                    and tpd.processDetailsid = pd.id
                  group by t.id, t.name, p.id, p.name;');
    
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    

    SQL Fiddle withDemo を参照してください。 。

    を覚えておいてください。 GROUP_CONCAT 列の文字列を作成する関数のデフォルトの最大長は1024であるため、この文字列に多くの文字を含める場合は、group_concat_max_lenのセッション値を変更する必要があります。 。

    このクエリは結果を返します:

    | TEAMID | TEAMNAME | PROCESSID | PROCESSNAME |  SHAPE | VEGETABLE |  FRUIT | ANIMAL |
    |      1 |    teamA |         1 |    processA | circle |    carrot |  apple | (null) |
    |      1 |    teamA |         2 |    processB | (null) |    (null) | (null) |    dog |
    



    1. mysql:timediff()を秒に変換します

    2. Mysqlで数値を単語に変換する

    3. SQL Server IFとIIF():違いは何ですか?

    4. SQLiteデータベースから取得した各アイテムを独自のTextviewに設定する方法