我有这三个表:
学生表:
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
我需要的是像这样的Pivot视图,但我不知道如何在MySQL中获得这样的结构:
id | student | week-1 | week-3 | week-9
1 | Charles | P | P | A
2 | Peter | A | A | P
3 | Mary | P | A | P
答案 0 :(得分: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
如果您要返回未知数量的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;
结果将是:
| 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
:< / p>
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