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つのテーブルから取得される特定の月の出席レポートを表示したいと思います。
this のようなレポートを表示したいと思います。
このタイプのデータの列から行へのローテーションは、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_admission
とcalendar
テーブルの間に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 |