在MySql中显示每月出勤报告


8

我正在使用Mysql DB在php中执行学校管理系统。我被困在我的项目中。请任何人提出我做错了什么。

我的数据库中有两个表。一种是存储Students记录,另一种是存储attendance

现在,我想显示当前月份特定班级所有学生的报告,无论他们是否在场。但是我仅在出勤表中捕获缺席学生的详细信息。

我已经编写了sql查询以在此处显示结果:

SELECT tab.class, attend, DATE, ta.rollno, ta.StdNm 
FROM tbl_absentees tab, tbl_admission ta
WHERE ta.Cls = class
  AND ta.rollno = tab.rollno
  AND class =22
  AND attend =  'A'
  AND DATE =  '2013-06-07';

结果是:

Class Attend RollNo StudentName

但是我想以31天表格的方式显示,如果出席者= A则缺席的日子显示A,否则只显示出勤表中的日期,否则显示剩余天数的'P'

我该如何在mysql中做到这一点?谁能建议/给我一个构想来实现这一目标。

抱歉,我的问题不明确。实际上,我想显示特定月份的出勤报告,其中数据来自两个表:

  • 第一个表由StudentName,RollNo,Class组成
  • 第二个表包含日期,状态,RollNo,类

现在我想显示象报告这样

Answers:


18

数据从列到行的这种旋转类型称为PIVOT。MySQL没有枢轴函数,但是您可以将聚合函数与CASE表达式一起使用以获取结果。

我的第一个建议是确定您是否有一个calendar表或一个包含要显示的所有日期的表。如果没有,那么我建议创建一个类似于以下内容的文件:

CREATE TABLE calendar (`Date` datetime) ;

INSERT INTO calendar (`Date`)
VALUES
    ('2013-06-01 00:00:00'),
    ('2013-06-02 00:00:00'),
    ('2013-06-03 00:00:00'),
    ('2013-06-04 00:00:00'),
    ('2013-06-05 00:00:00'),
    ('2013-06-06 00:00:00'),
    ('2013-06-07 00:00:00'),
    ('2013-06-08 00:00:00'),
    ('2013-06-09 00:00:00'),
    ('2013-06-10 00:00:00');

这将使您能够生成要显示的所有日期的列表。

其次,您将需要生成每个学生和每个日期的列表。您可以通过tbl_admissioncalendar表和表之间使用CROSS JOIN来做到这一点:

select c.date, a.studentname, a.rollno, a.class
from calendar c
cross join tbl_admission a;

参见演示。获得此列表后,您可以对现有tbl_absentees表使用LEFT JOIN 来获得结果:

select 
  ca.studentname,
  ca.rollno,
  ca.class,
  max(case when ca.date = '2013-06-01' then coalesce(p.status, 'P') end) `2013-06-01`,
  max(case when ca.date = '2013-06-02' then coalesce(p.status, 'P') end) `2013-06-02`,
  max(case when ca.date = '2013-06-03' then coalesce(p.status, 'P') end) `2013-06-03`,
  max(case when ca.date = '2013-06-04' then coalesce(p.status, 'P') end) `2013-06-04`,
  max(case when ca.date = '2013-06-05' then coalesce(p.status, 'P') end) `2013-06-05`,
  max(case when ca.date = '2013-06-06' then coalesce(p.status, 'P') end) `2013-06-06`,
  max(case when ca.date = '2013-06-07' then coalesce(p.status, 'P') end) `2013-06-07`,
  max(case when ca.date = '2013-06-08' then coalesce(p.status, 'P') end) `2013-06-08`,
  max(case when ca.date = '2013-06-08' then coalesce(p.status, 'P') end) `2013-06-09`,
  max(case when ca.date = '2013-06-10' then coalesce(p.status, 'P') end) `2013-06-10`
from
(
  select c.date, a.studentname, a.rollno, a.class
  from calendar c
  cross join tbl_admission a
) ca
left join tbl_absentees p
  on ca.rollno = p.rollno
  and ca.date = p.date
group by ca.studentname, ca.rollno, ca.class
order by ca.rollno;

请参阅带有演示的SQL Fiddle。当然,对于您的请求,您很可能希望根据日期范围查询数据,因此您将不希望对值进行硬编码。如果是这种情况,那么您将需要查看使用准备好的语句来生成动态SQL:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(CASE WHEN ca.date = ''',
      date_format(date, '%Y-%m-%d'),
      ''' THEN coalesce(p.status, ''P'') END) AS `',
      date_format(date, '%Y-%m-%d'), '`'
    )
  ) INTO @sql
FROM calendar
where date>='2013-06-01'
  and date <= '2013-06-05';

SET @sql 
  = CONCAT('SELECT ca.studentname,
              ca.rollno,
              ca.class, ', @sql, ' 
            from
            (
              select c.date, a.studentname, a.rollno, a.class
              from calendar c
              cross join tbl_admission a
            ) ca
            left join tbl_absentees p
              on ca.rollno = p.rollno
              and ca.date = p.date
            where ca.date>=''2013-06-01''
              and ca.date <= ''2013-06-05''
            group by ca.studentname, ca.rollno, ca.class
            order by ca.rollno');

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

请参阅带有演示的SQL Fiddle。这两个查询将给出类似于以下结果:

| STUDENTNAME | ROLLNO | CLASS | 2013-06-01 | 2013-06-02 | 2013-06-03 | 2013-06-04 | 2013-06-05 | 2013-06-06 | 2013-06-07 | 2013-06-08 | 2013-06-09 | 2013-06-10 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------
|       Naren |      1 |    22 |          A |          A |          A |          A |          P |          P |          P |          P |          P |          P |
|       Srinu |      2 |    22 |          P |          P |          P |          P |          P |          P |          P |          P |          P |          P |
|        Blah |      3 |    22 |          A |          P |          P |          P |          P |          P |          P |          P |          P |          P |
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.