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:
Maintenant, je veux afficher un rapport comme this .
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 |