【问题标题】:Attendance system in mysql [closed]mysql中的考勤系统[关闭]
【发布时间】:2013-03-26 13:46:17
【问题描述】:

我有这三个表:

学生桌:

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

【问题讨论】:

    标签: mysql view pivot


    【解决方案1】:

    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 Fiddle with Demo

    如果您想要返回未知数量的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 Fiddle with Demo

    结果将是:

    | 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 Fiddle with Demo

    【讨论】:

    • Bluefeet,感谢您的回答。它解决了我的问题。出于任何原因,我不能在我的服务器中使用动态 SQL。我已经尝试过 HeidiSQL 和 phpMyAdmin。
    • @Vanderlei 我不知道为什么你不能使用动态 SQL,你会收到错误吗?
    • 我试图通过这段代码创建一个视图,但 phpMyAdmin 不允许。
    • @Vanderlei 动态 SQL 需要在一个过程中
    • #1243 - 未知的准备好的语句处理程序 (stmt) 给 EXECUTE
    猜你喜欢
    • 2020-11-11
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2019-10-12
    相关资源
    最近更新 更多