-4

私はこれらの3つのテーブルを持っています:

学生テーブル:

id | name
1  | Charles
2  | Peter
3  | Mary
4  | John
5  | Mike
...

週の表:

id | week | year
1  | 1    | 2012
2  | 3    | 2012
3  | 6    | 2012
4  | 8    | 2012
5  | 9    | 2012
6  | 12   | 2012
...

出席表:

id | student | week | control
1  | 1       | 1    | P (present)
1  | 2       | 1    | A (absent)
1  | 1       | 3    | P
1  | 2       | 3    | A
1  | 3       | 9    | P

必要なのはこのようなピボットビューですが、MySQLでそのような構造を取得する方法がわかりません。

id | student | week-1 | week-3 | week-9
1  | Charles | P      | P      | A
2  | Peter   | A      | A      | P
3  | Mary    | P      | A      | P
4

1 に答える 1

3

MySQLにはピボット関数はありませんが、CASE式を含む集計関数を使用して複製できます。コードは次のようになります。

select s.id,
  s.name,
  max(case when week=1 then control else 'A' end) Week1,
  max(case when week=3 then control else 'A' end) Week3,
  max(case when week=9 then control else 'A' end) Week9
from students s
inner join attendance a
  on s.id = a.student
group by s.id, s.name

SQL FiddlewithDemoを参照してください

返す値の数が不明な場合weekは、プリペアドステートメントで動的SQLを使用する必要があります。コードは次のようになります。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(CASE WHEN week = ',
      week,
      ' THEN control else ''A'' END) AS week',
      week
    )
  ) INTO @sql
FROM weeks;

SET @sql 
  = CONCAT('SELECT s.id,
              s.name, ', @sql, ' 
            from students s
            inner join attendance a
              on s.id = a.student
            group by s.id, s.name');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SQL FiddlewithDemoを参照してください

結果は次のようになります。

| ID |    NAME | WEEK1 | WEEK3 | WEEK6 | WEEK8 | WEEK9 | WEEK12 |
-----------------------------------------------------------------
|  1 | Charles |     P |     P |     A |     A |     A |      A |
|  2 |   Peter |     A |     A |     A |     A |     A |      A |
|  3 |    Mary |     A |     A |     A |     A |     P |      A |

Students注:テーブルに一致する行があるかどうかに関係なく、テーブル内のすべてを返したい場合は、 :attendanceを使用する必要があります。LEFT JOIN

select s.id,
  s.name,
  max(case when week=1 then control else 'A' end) Week1,
  max(case when week=3 then control else 'A' end) Week3,
  max(case when week=9 then control else 'A' end) Week9
from students s
left join attendance a
  on s.id = a.student
group by s.id, s.name

SQL FiddlewithDemoを参照してください。

于 2013-03-26T14:00:05.493 に答える