Hiển thị Báo cáo tham dự hàng tháng trong MySql


8

Tôi đang làm một hệ thống quản lý trường học bằng php bằng Mysql DB. Tôi bị mắc kẹt trong Dự án của tôi. Xin mọi người đề nghị những gì tôi đang làm sai.

Tôi có hai bảng trong cơ sở dữ liệu của mình; Một là lưu trữ Studentshồ sơ, một là lưu trữ attendancengày của họ một cách khôn ngoan

Bây giờ tôi muốn hiển thị một báo cáo của tất cả các sinh viên trong lớp cụ thể cho tháng hiện tại cho dù họ có mặt hay vắng mặt. Nhưng tôi chỉ nắm bắt được chi tiết sinh viên vắng mặt trong bảng điểm danh.

Tôi đã viết truy vấn sql để hiển thị kết quả ở đây là:

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

Kết quả là:

Class Attend RollNo StudentName

Nhưng tôi muốn hiển thị theo cách thức bảng 31 ngày bằng cách chỉ lấy Ngày trong bảng tham dự nếu tham dự = Màn hình A cho những ngày vắng mặt nếu không Hiển thị 'P' cho những ngày còn lại

Làm thế nào tôi có thể làm điều này trong mysql? Bất cứ ai có thể đề nghị / cho tôi một ý tưởng để đạt được điều này.

Xin lỗi vì đã thông báo sai trong câu hỏi của tôi. Trên thực tế tôi muốn hiển thị một báo cáo tham dự cho một tháng cụ thể trong đó dữ liệu đến từ hai bảng:

  • bảng đầu tiên bao gồm StudentName, RollNo, Class
  • bảng thứ hai bao gồm Ngày, Trạng thái, Cuộn Không, Lớp

Bây giờ tôi muốn hiển thị báo cáo như thế này .

Câu trả lời:


18

Kiểu xoay vòng dữ liệu từ cột này sang hàng khác được gọi là PIVOT. MySQL không có chức năng xoay vòng nhưng bạn có thể sử dụng hàm tổng hợp với biểu thức CASE để nhận kết quả.

Đề xuất đầu tiên của tôi sẽ là xác định xem bạn có một calendarbảng hoặc một bảng có chứa tất cả các ngày mà bạn muốn hiển thị. Nếu không, thì tôi khuyên bạn nên tạo một cái tương tự như sau:

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

Điều này sẽ giúp bạn có thể tạo một danh sách tất cả các ngày mà bạn muốn hiển thị.

Thứ hai, bạn sẽ cần tạo danh sách của từng sinh viên và mỗi ngày. Bạn có thể làm điều này bằng cách sử dụng CROSS THAM GIA giữa bạn tbl_admissioncalendarbảng:

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

Xem bản demo . Khi bạn có danh sách này, sau đó bạn có thể sử dụng TRÁI PHIẾU vào tbl_absenteesbảng hiện có của mình để nhận kết quả:

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;

Xem SQL Fiddle với Demo . Tất nhiên đối với yêu cầu của bạn, rất có thể bạn muốn truy vấn dữ liệu dựa trên phạm vi ngày để bạn không muốn mã hóa các giá trị. Nếu đó là trường hợp, thì bạn sẽ cần xem xét việc sử dụng một câu lệnh được chuẩn bị để tạo SQL động:

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;

Xem SQL Fiddle với Demo . Cả hai truy vấn này sẽ cho kết quả tương tự như:

| 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 |
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.