MySQLの行列変換で複数条件指定


1日に4時限あり，複数クラスの割当表を作成しています。  
最低1時限から受講者は参加し，最大4時限で，どの組にも参加できます。  
もちろん参加しないで空くこともあります。

DBには左側のようにレコードが保存されていて，それを行列変換したいのですが，行き詰っています。

どうぞよろしくお願いします。

[![左がDB格納状態のテーブル。右側が出力させたい形式](https://i.stack.imgur.com/i3KGE.png)](https://i.stack.imgur.com/i3KGE.png)




一般的にこう言う操作はピボット(PIVOT)と言いますので、そういうキーワードで調べれば答えが見つかります。SQLでなくてもflattenとかflatMapとか、よくある操作です。

ご希望の結果とは若干違うかもしれませんがMySQLであればGROUP_CONCATを使うと、SELECTしてきた文字列をカンマ区切りの文字列に変換できます。SEPARATORを指定すればカンマ以外の文字を指定することもできます。

組をcls,名前をname,時限をperiodとして、テーブルを作成して、実験した結果です。

[code]

    create table t1 (
      cls varchar(1),
      name varchar(1),
      period varchar(1)
    );
    
[/code]

このテーブルにデータを入れて

[code]

    insert into t1 values(1,'a',1), (1,'b',1), (2,'c',1), (2,'d',1), (3,'e',1), (3,'f',1), (4,'g',1), (4,'h',1), (1,'a',2), (1,'c',2), (2,'i',2), (2,'j',2), (3,'k',2), (3,'l',2), (4,'m',2), (4,'b',2), (1,'n',3), (1,'o',3), (2,'p',3), (2,'q',3), (3,'r',3), (3,'s',3), (4,'t',3), (4,'u',3), (1,'v',4), (1,'w',4), (2,'x',4), (2,'a',4), (3,'f',4), (3,'h',4), (4,'y',4), (4,'z',4);
    
[/code]

SELECTを実行します。

[code]

    select cls,
           group_concat(case when period=1 then name end order by 1) as period1,
           group_concat(case when period=2 then name end order by 1) as period2,
           group_concat(case when period=3 then name end order by 1) as period3,
           group_concat(case when period=4 then name end order by 1) as period4
    from t1
    group by cls
    order by cls
    
[/code]

結果

[code]

    cls      period1    period2    period3    period4
    1        a,b        a,c        n,o        v,w
    2        c,d        i,j        p,q        a,x
    3        e,f        k,l        r,s        f,h
    4        g,h        b,m        t,u        y,z
    
[/code]

追記：受講者の名前のソートを追加しました。




一般的にこう言う操作はピボット(PIVOT)と言いますので、そういうキーワードで調べれば答えが見つかります。SQLでなくてもflattenとかflatMapとか、よくある操作です。

ご希望の結果とは若干違うかもしれませんがMySQLであればGROUP_CONCATを使うと、SELECTしてきた文字列をカンマ区切りの文字列に変換できます。SEPARATORを指定すればカンマ以外の文字を指定することもできます。

組をcls,名前をname,時限をperiodとして、テーブルを作成して、実験した結果です。

[code]

    create table t1 (
      cls varchar(1),
      name varchar(1),
      period varchar(1)
    );
    
[/code]

このテーブルにデータを入れて

[code]

    insert into t1 values(1,'a',1), (1,'b',1), (2,'c',1), (2,'d',1), (3,'e',1), (3,'f',1), (4,'g',1), (4,'h',1), (1,'a',2), (1,'c',2), (2,'i',2), (2,'j',2), (3,'k',2), (3,'l',2), (4,'m',2), (4,'b',2), (1,'n',3), (1,'o',3), (2,'p',3), (2,'q',3), (3,'r',3), (3,'s',3), (4,'t',3), (4,'u',3), (1,'v',4), (1,'w',4), (2,'x',4), (2,'a',4), (3,'f',4), (3,'h',4), (4,'y',4), (4,'z',4);
    
[/code]

SELECTを実行します。

[code]

    select cls,
           group_concat(case when period=1 then name end order by 1) as period1,
           group_concat(case when period=2 then name end order by 1) as period2,
           group_concat(case when period=3 then name end order by 1) as period3,
           group_concat(case when period=4 then name end order by 1) as period4
    from t1
    group by cls
    order by cls
    
[/code]

結果

[code]

    cls      period1    period2    period3    period4
    1        a,b        a,c        n,o        v,w
    2        c,d        i,j        p,q        a,x
    3        e,f        k,l        r,s        f,h
    4        g,h        b,m        t,u        y,z
    
[/code]

追記：受講者の名前のソートを追加しました。

