Exibir relatório de presença mensal no MySql

8

Estou fazendo um sistema de gerenciamento de escola em php usando o MySQL DB. Estou preso no meu projeto. Por favor, alguém sugira o que estou fazendo de errado.

Eu tenho duas tabelas no meu banco de dados; um é armazenar Studentsregistros outro é armazenar seus attendancedias sábios

Agora, quero exibir um relatório de todos os alunos da turma em particular para o mês atual, estejam eles presentes ou ausentes. Mas estou capturando apenas os detalhes dos alunos ausentes apenas na tabela de presença.

Eu escrevi consulta sql para exibir o resultado aqui é:

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';

O resultado é:

Class Attend RollNo StudentName

Mas eu quero exibir da maneira de tabela de 31 dias apenas com Data na tabela de presença, se comparecer = A exibir A por dias ausentes, caso contrário, exibir 'P' nos dias restantes

Como posso fazer isso no mysql? Alguém pode sugerir / me dar uma idéia para conseguir isso.

Desculpe por esclarecimentos incorretos na minha pergunta. Na verdade, quero exibir um relatório de presença para um mês específico em que os dados vêm de duas tabelas:

  • a primeira tabela consiste em StudentName, RollNo, Class
  • a segunda tabela consiste em Data, Status, RollNo, Classe

Agora eu quero exibir um relatório como este .

Narendar_CH
fonte

Respostas:

18

Esse tipo de rotação de dados de colunas para linhas é conhecido como PIVOT. O MySQL não possui uma função dinâmica, mas você pode usar uma função agregada com uma expressão CASE para obter o resultado.

Minha primeira sugestão seria determinar se você tem uma calendartabela ou uma tabela que contém todas as datas que você deseja exibir. Caso contrário, sugiro criar um semelhante ao seguinte:

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');

Isso permitirá gerar uma lista de todas as datas que você deseja exibir.

Segundo, você precisará gerar a lista de cada aluno e cada data. Você pode fazer isso usando um CROSS JOIN entre você tbl_admissione a calendartabela:

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

Veja a demonstração . Depois de ter essa lista, você pode usar um LEFT JOIN na sua tbl_absenteestabela existente para obter o resultado:

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;

Consulte SQL Fiddle com demonstração . Obviamente, para sua solicitação, é provável que você deseje consultar os dados com base em um período, para não codificar os valores. Se for esse o caso, será necessário usar uma instrução preparada para gerar SQL dinâmico:

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;

Consulte SQL Fiddle com demonstração . Ambas as consultas fornecerão um resultado semelhante a:

| 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 |
Taryn
fonte