web-dev-qa-db-fra.com

Afficher le rapport mensuel de présence dans MySql

Je fais un système de gestion scolaire en php en utilisant Mysql DB. Je suis coincé dans mon projet. S'il vous plaît, quelqu'un suggère ce que je fais mal.

J'ai deux tables dans ma base de données; l'un consiste à stocker Students enregistrements un autre consiste à stocker leurs attendance jour par jour

Maintenant, je veux afficher un rapport de tous les élèves d'une classe particulière pour le mois en cours, qu'ils soient présents ou absents. Mais je ne saisis que les détails des élèves absents uniquement dans le tableau des présences.

J'ai écrit une requête SQL pour afficher le résultat ici:

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

Le résultat est:

Class Attend RollNo StudentName

Mais je souhaite afficher le tableau de 31 jours en prenant uniquement la date dans le tableau de présence si assister = un affichage A pour les jours d'absence sinon afficher "P" pour les jours restants

Comment puis-je faire cela dans mysql? Quelqu'un peut-il suggérer/me donner une idée pour y parvenir?.

Désolé pour une mauvaise déclaration dans ma question. En fait, je veux afficher un rapport de présence pour un mois particulier où les données proviennent de deux tableaux:

  • la première table se compose de StudentName, RollNo, Class
  • la deuxième table se compose de Date, Status, RollNo, Class

Maintenant, je veux afficher un rapport comme this .

8
Narendar_CH

Ce type de rotation des données des colonnes vers les lignes est appelé PIVOT. MySQL n'a pas de fonction pivot mais vous pouvez utiliser une fonction d'agrégation avec une expression CASE pour obtenir le résultat.

Ma première suggestion serait de déterminer si vous avez une table calendar ou une table qui contient toutes les dates que vous souhaitez afficher. Sinon, je suggérerais d'en créer un semblable au suivant:

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

Cela vous permettra de générer une liste de toutes les dates que vous souhaitez afficher.

Deuxièmement, vous devrez générer la liste de chaque étudiant et chaque date. Vous pouvez le faire en utilisant un CROSS JOIN entre votre tbl_admission et la table calendar:

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

Voir Démo . Une fois que vous avez cette liste, vous pouvez utiliser un LEFT JOIN à votre tbl_absentees table pour obtenir le résultat:

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;

Voir SQL Fiddle with Demo . Bien sûr, pour votre demande, vous souhaiterez probablement interroger les données en fonction d'une plage de dates afin de ne pas vouloir coder en dur Si c'est le cas, vous devrez alors utiliser une instruction préparée pour générer du SQL dynamique:

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;

Voir SQL Fiddle with Demo . Ces deux requêtes donneront un résultat similaire à:

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