Được rồi, hãy thử cái này và xem nó có hoạt động không.
Đây là lược đồ tôi có một số. Nó rất đơn giản nhưng hỗ trợ trường hợp sử dụng của bạn.
CREATE TABLE employees (
id int unsigned auto_increment,
name varchar(255),
PRIMARY KEY(id)
);
CREATE TABLE leave_type (
id int unsigned auto_increment,
name varchar(255),
PRIMARY KEY(id)
);
CREATE TABLE leave_log (
id int unsigned auto_increment,
leave_type_id int unsigned,
employee_id int unsigned,
is_full_day int unsigned,
is_half_day int unsigned,
PRIMARY KEY(id)
);
Một số dữ liệu thử nghiệm ...
INSERT INTO employees VALUES (14, 'Lisa'), (15, 'Homer'), (13, 'Bart');
INSERT INTO leave_type VALUES (1, 'Annual'), (2, 'Unpaid'), (3, 'Exam');
INSERT INTO leave_log VALUES (NULL, 3, 14, 1, 0), (NULL, 1, 14, 1, 0), (NULL, 1, 14, 0, 1), (NULL, 1, 14, 0, 1);
INSERT INTO leave_log VALUES (NULL, 2, 15, 0, 1);
INSERT INTO leave_log VALUES (NULL, 3, 13, 1, 0), (NULL, 1, 13, 1, 0);
Đừng tập trung quá nhiều vào tên cột và định nghĩa, tôi không đánh bóng sơ đồ nào cả vì tôi không biết đủ về ứng dụng của bạn để làm điều này.
Khi lược đồ được tạo và có dữ liệu ở đó, truy vấn khá đơn giản này sẽ làm được những gì bạn muốn.
SELECT e.name, SUM(annual.is_half_day), SUM(unpaid.is_half_day), SUM(exam.is_half_day),
SUM(annual.is_full_day), SUM(unpaid.is_full_day), SUM(exam.is_full_day)
FROM employees e
LEFT JOIN leave_log annual ON annual.leave_type_id = 1 AND annual.employee_id = e.id
LEFT JOIN leave_log unpaid ON unpaid.leave_type_id = 2 AND unpaid.employee_id = e.id
LEFT JOIN leave_log exam ON exam.leave_type_id = 3 AND exam.employee_id = e.id
GROUP BY e.id
Có một cái nhìn và xem những gì bạn nghĩ. Đây có phải là một ứng dụng có hiệu suất cao hoặc được tải nhiều không?
CHỈNH SỬA
Truy vấn này liên quan nhiều hơn và có thể sẽ có một số hạn chế về hiệu suất nhưng có thể chính xác hơn.
SELECT e.name, e.id,
IFNULL(annual_half.total, 0) annual_half,
IFNULL(unpaid_half.total, 0) unpaid_half,
IFNULL(exam_half.total, 0) exam_half,
IFNULL(annual_full.total, 0) annual_full,
IFNULL(unpaid_full.total, 0) unpaid_full,
IFNULL(exam_full.total, 0) exam_full
FROM employees e
LEFT JOIN ( SELECT SUM(is_full_day) as total, employee_id, leave_type_id FROM leave_log WHERE is_full_day = 1 AND leave_type_id = 1 GROUP BY 3, 2) annual_full ON annual_full.employee_id = e.id
LEFT JOIN ( SELECT SUM(is_full_day) as total, employee_id, leave_type_id FROM leave_log WHERE is_full_day = 1 AND leave_type_id = 2 GROUP BY 3, 2) unpaid_full ON unpaid_full.employee_id = e.id
LEFT JOIN ( SELECT SUM(is_full_day) as total, employee_id, leave_type_id FROM leave_log WHERE is_full_day = 1 AND leave_type_id = 3 GROUP BY 3, 2) exam_full ON exam_full.employee_id = e.id
LEFT JOIN ( SELECT SUM(is_half_day) as total, employee_id, leave_type_id FROM leave_log WHERE is_half_day = 1 AND leave_type_id = 1 GROUP BY 3, 2) annual_half ON annual_half.employee_id = e.id
LEFT JOIN ( SELECT SUM(is_half_day) as total, employee_id, leave_type_id FROM leave_log WHERE is_half_day = 1 AND leave_type_id = 2 GROUP BY 3, 2) unpaid_half ON unpaid_half.employee_id = e.id
LEFT JOIN ( SELECT SUM(is_half_day) as total, employee_id, leave_type_id FROM leave_log WHERE is_half_day = 1 AND leave_type_id = 3 GROUP BY 3, 2) exam_half ON exam_half.employee_id = e.id
GROUP BY 1;