Monatlichen Anwesenheitsbericht in MySql anzeigen


8

Ich mache ein Schulverwaltungssystem in PHP mit MySQL DB. Ich stecke in meinem Projekt fest. Bitte schlägt jemand vor, was ich falsch mache.

Ich habe zwei Tabellen in meiner Datenbank; ist zum Speichern von StudentsAufzeichnungen ist eine andere sie speichern attendanceTag wiese

Jetzt möchte ich einen Bericht aller Schüler in einer bestimmten Klasse für den aktuellen Monat anzeigen, unabhängig davon, ob sie anwesend oder abwesend waren. Aber ich erfasse nur die Details der abwesenden Schüler nur in der Anwesenheitstabelle.

Ich habe eine SQL-Abfrage geschrieben, um das Ergebnis hier anzuzeigen:

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

Das Ergebnis ist:

Class Attend RollNo StudentName

Aber ich möchte in 31-Tage-Tabelle anzeigen, indem ich nur das Datum in der Anwesenheitstabelle nehme, wenn Anwesenheit = A Anzeige A für abwesende Tage, andernfalls 'P' für verbleibende Tage anzeigen

Wie kann ich das in MySQL machen? Kann mir jemand eine Idee vorschlagen / geben, um dies zu erreichen.

Entschuldigung für die falsche Erklärung in meiner Frage. Eigentlich möchte ich einen Anwesenheitsbericht für einen bestimmten Monat anzeigen, in dem Daten aus zwei Tabellen stammen:

  • Die erste Tabelle besteht aus StudentName, RollNo, Class
  • Die zweite Tabelle besteht aus Datum, Status, Rollennummer, Klasse

Jetzt möchte ich berichten , wie angezeigt werden diese .

Antworten:


18

Diese Art der Rotation von Daten von Spalten zu Zeilen wird als PIVOT bezeichnet. MySQL hat keine Pivot-Funktion, aber Sie können eine Aggregatfunktion mit einem CASE-Ausdruck verwenden, um das Ergebnis zu erhalten.

Mein erster Vorschlag wäre, festzustellen, ob Sie eine calendarTabelle oder eine Tabelle haben, die alle Daten enthält, die Sie anzeigen möchten. Wenn nicht, würde ich vorschlagen, eine ähnliche zu erstellen:

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

Auf diese Weise können Sie eine Liste aller Daten erstellen, die Sie anzeigen möchten.

Zweitens müssen Sie die Liste jedes Schülers und jedes Datums erstellen. Sie können dies tun, indem Sie einen CROSS JOIN zwischen Ihrem tbl_admissionund dem calendarTisch verwenden:

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

Siehe Demo . Sobald Sie diese Liste haben, können Sie einen LEFT JOIN zu Ihrer vorhandenen tbl_absenteesTabelle verwenden, um das Ergebnis zu erhalten:

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;

Siehe SQL Fiddle mit Demo . Natürlich möchten Sie für Ihre Anfrage höchstwahrscheinlich die Daten basierend auf einem Datumsbereich abfragen, damit Sie die Werte nicht fest codieren möchten. Wenn dies der Fall ist, müssen Sie eine vorbereitete Anweisung verwenden, um dynamisches SQL zu generieren:

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;

Siehe SQL Fiddle mit Demo . Beide Abfragen ergeben ein ähnliches Ergebnis wie:

| 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 |
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.