Visualizza il rapporto mensile delle presenze in MySql


8

Sto facendo un sistema di gestione della scuola in php usando Mysql DB. Sono bloccato nel mio progetto. Per favore qualcuno suggerisce cosa sto facendo di sbagliato.

Ho due tabelle nel mio database; uno è quello di memorizzare i Studentsrecord un altro è quello di memorizzare il loro attendancegiorno saggio

Ora voglio mostrare un rapporto di tutti gli studenti in una determinata classe per il mese corrente, sia che siano presenti o assenti. Ma sto acquisendo solo i dettagli degli studenti assenti solo nella tabella delle presenze.

Ho scritto query sql per visualizzare il risultato qui è:

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

Il risultato è:

Class Attend RollNo StudentName

Ma voglio visualizzare in modalità tabella 31 giorni prendendo solo la data nella tabella delle presenze se attend = A mostra A per giorni assenti altrimenti visualizza 'P' per i giorni rimanenti

Come posso farlo in mysql? Qualcuno può suggerirmi / darmi un'idea per raggiungere questo obiettivo.

Ci scusiamo per la dichiarazione errata nella mia domanda. In realtà voglio visualizzare un rapporto di presenza per un determinato mese in cui i dati provengono da due tabelle:

  • la prima tabella è composta da StudentName, RollNo, Class
  • la seconda tabella è composta da Data, Stato, RollNo, Classe

Ora voglio visualizzare un report come questo .

Risposte:


18

Questo tipo di rotazione dei dati dalle colonne alle righe è noto come PIVOT. MySQL non ha una funzione pivot ma puoi ottenere una funzione aggregata con un'espressione CASE per ottenere il risultato.

Il mio primo suggerimento sarebbe quello di determinare se si dispone di una calendartabella o una tabella che contiene tutte le date che si desidera visualizzare. In caso contrario, suggerirei di crearne uno simile al seguente:

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

Ciò consentirà di generare un elenco di tutte le date che si desidera visualizzare.

In secondo luogo, dovrai generare l'elenco di ogni studente e ogni data. Puoi farlo usando un CROSS JOIN tra il tuo tbl_admissione il calendartavolo:

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

Vedi la demo . Una volta che hai questo elenco, puoi utilizzare un JOIN SINISTRA per la tbl_absenteestabella esistente per ottenere il risultato:

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;

Vedi SQL Fiddle with Demo . Naturalmente per la tua richiesta, molto probabilmente vorrai interrogare i dati in base a un intervallo di date, quindi non vorrai codificare i valori. In tal caso, dovrai guardare usando un'istruzione preparata per generare SQL dinamico:

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;

Vedi SQL Fiddle with Demo . Entrambe queste query daranno un risultato simile 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 |
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.