Mostrar el informe de asistencia mensual en MySql

8

Estoy haciendo un sistema de gestión escolar en php usando Mysql DB. Estoy atrapado en mi proyecto. Por favor, alguien sugiera lo que estoy haciendo mal.

Tengo dos tablas en mi base de datos; uno es almacenar Studentsregistros otro es almacenar su attendancedía sabio

Ahora quiero mostrar un informe de todos los estudiantes en una clase en particular para el mes actual, ya sea que estén presentes o ausentes. Pero solo estoy capturando los detalles de los estudiantes ausentes solo en la tabla de asistencia.

He escrito consulta SQL para mostrar el resultado aquí es:

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

El resultado es:

Class Attend RollNo StudentName

Pero quiero mostrar en forma de tabla de 31 días tomando solo Fecha en la tabla de asistencia si asistir = A mostrar A por días ausentes De lo contrario, mostrar 'P' para los días restantes

¿Cómo puedo hacer esto en mysql? ¿Alguien puede sugerirme / darme una idea para lograr esto?

Perdón por la aclaración en mi pregunta. En realidad, quiero mostrar un informe de asistencia para un mes en particular donde los datos provienen de dos tablas:

  • la primera tabla consta de StudentName, RollNo, Class
  • la segunda tabla consiste en Fecha, Estado, Número de lista, Clase

Ahora quiero mostrar informes como este .

Narendar_CH
fuente

Respuestas:

18

Este tipo de rotación de datos de columnas a filas se conoce como PIVOT. MySQL no tiene una función pivote, pero puede usar una función agregada con una expresión CASE para obtener el resultado.

Mi primera sugerencia sería determinar si tiene una calendartabla o una tabla que contenga todas las fechas que desea mostrar. Si no, entonces sugeriría crear uno similar al siguiente:

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

Esto le permitirá generar una lista de todas las fechas que desea mostrar.

En segundo lugar, deberá generar la lista de cada alumno y cada fecha. Puede hacer esto utilizando una CROSS JOIN entre su tbl_admissiony la calendartabla:

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

Ver demo . Una vez que tenga esta lista, puede usar una UNIÓN IZQUIERDA a su tbl_absenteestabla existente para obtener el 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;

Ver SQL Fiddle con Demo . Por supuesto, para su solicitud, lo más probable es que desee consultar los datos en función de un rango de fechas, por lo que no querrá codificar los valores. Si ese es el caso, deberá considerar el uso de una declaración preparada para generar 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;

Ver SQL Fiddle con Demo . Ambas consultas darán un resultado similar 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
fuente