web-dev-qa-db-ja.com

MySqlで月次出席レポートを表示する

Mysql DBを使用して、phpで学校管理システムを実行しています。プロジェクトで立ち往生しています。誰かが私が間違っていることを提案してください。

データベースに2つのテーブルがあります。 1つはStudentsレコードを保存する方法で、もう1つはattendanceを1日ごとに保存する方法です。

今、私は今月の特定のクラスのすべての学生のレポートを表示したいと思います。ただし、欠席している学生の詳細のみを出席表でのみキャプチャしています。

ここに結果を表示するSQLクエリを作成しました。

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

結果は次のとおりです。

Class Attend RollNo StudentName

しかし、出席= Aの場合は出席表の日付のみを取り、31日の表の方法で表示したいのですが、欠席の場合はAを表示し、それ以外の場合は残りの日には「P」を表示します

Mysqlでこれを行うにはどうすればよいですか?誰かがこれを達成するためのアイデアを私に提案/与えることができますか?.

私の質問を誤解して申し訳ありません。実際には、データが2つのテーブルから取得される特定の月の出席レポートを表示したいと思います。

  • 最初のテーブルは、StudentName、RollNo、Classで構成されています
  • 2番目のテーブルは、日付、ステータス、RollNo、クラスで構成されます

this のようなレポートを表示したいと思います。

8
Narendar_CH

このタイプのデータの列から行へのローテーションは、PIVOTと呼ばれます。 MySQLにはピボット関数はありませんが、CASE式で集計関数を使用して結果を取得できます。

私の最初の提案は、calendarテーブルか、表示するすべての日付を含むテーブルがあるかどうかを判断することです。そうでない場合は、次のようなものを作成することをお勧めします。

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

これにより、表示するすべての日付のリストを生成できるようになります。

次に、各学生と各日付のリストを生成する必要があります。これを行うには、tbl_admissioncalendarテーブルの間にCROSS JOINを使用します。

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

Demo を参照してください。このリストを取得したら、既存のtbl_absenteesテーブルにLEFT JOINを使用して結果を取得できます。

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;

SQL Fiddle with Demo を参照してください。もちろん、リクエストの場合は、日付範囲に基づいてデータをクエリするので、ハードコードする必要はありません。その場合は、準備済みステートメントを使用して動的SQLを生成する方法を確認する必要があります。

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;

SQL Fiddle with Demo を参照してください。これらのクエリは両方とも、次のような結果になります。

| 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