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 calendar
bả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_admission
và calendar
bả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_absentees
bả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 |