Bài này mở rộng WHERE với các toán tử thường dùng khi làm tìm kiếm và báo cáo: LIKE với ký tự đại diện, IN, BETWEEN, xử lý NULL đúng cách, và biểu thức CASE để phân loại ngay trong truy vấn.
- Tìm kiếm theo mẫu với LIKE, % và _
- Dùng IN, NOT IN, BETWEEN
- Hiểu logic ba giá trị và IS NULL, IFNULL, COALESCE
- Phân loại bằng CASE WHEN
Khái niệm và lý thuyết
Mọi so sánh với NULL cho kết quả UNKNOWN, không phải TRUE: WHERE email = NULL không trả về dòng nào. Phải dùng IS NULL/IS NOT NULL. NULL nghĩa là “chưa biết”, khác chuỗi rỗng và khác 0; hàm tổng hợp bỏ qua NULL.
LIKE và ký tự đại diện
SELECT ho_ten FROM sinhvien WHERE ho_ten LIKE 'Lò%'; -- bắt đầu bằng Lò
SELECT ho_ten FROM sinhvien WHERE ho_ten LIKE '%Thị%'; -- chứa Thị
SELECT ho_ten FROM sinhvien WHERE ho_ten LIKE '%An'; -- kết thúc bằng An
SELECT ma_sv FROM sinhvien WHERE ma_sv LIKE 'SV00_'; -- _ : đúng một ký tự
SELECT ho_ten FROM sinhvien WHERE ho_ten NOT LIKE '%Văn%';
SELECT ho_ten FROM sinhvien WHERE ho_ten REGEXP '^(Lò|Vì) '; -- biểu thức chính quyTìm kiếm trong PHP: WHERE ho_ten LIKE ? với tham số "%$q%". LIKE bắt đầu bằng % không dùng được chỉ mục, chậm với bảng rất lớn; khi đó dùng FULLTEXT.
IN và BETWEEN
SELECT ho_ten, que_quan FROM sinhvien WHERE que_quan IN ('Sơn La', 'Điện Biên', 'Lai Châu');
SELECT ho_ten FROM sinhvien WHERE lop_id NOT IN (1, 2);
SELECT * FROM diem WHERE diem BETWEEN 7 AND 8.5; -- bao gồm hai đầu
SELECT ho_ten FROM sinhvien WHERE ngay_sinh BETWEEN '2006-01-01' AND '2006-06-30';
SELECT ho_ten FROM sinhvien WHERE ngay_sinh NOT BETWEEN '2006-01-01' AND '2006-12-31';
-- IN với truy vấn con (bài JOIN nói thêm)
SELECT ho_ten FROM sinhvien WHERE id IN (SELECT sinhvien_id FROM diem WHERE diem >= 9);NULL
SELECT ho_ten FROM sinhvien WHERE email IS NULL; -- chưa có email
SELECT ho_ten FROM sinhvien WHERE email IS NOT NULL;
SELECT ho_ten, IFNULL(email, 'chưa có') AS email FROM sinhvien;
SELECT ho_ten, COALESCE(email, que_quan, 'N/A') FROM sinhvien; -- giá trị đầu tiên khác NULL
SELECT * FROM diem WHERE diem IS NULL; -- chưa có điểm
SELECT AVG(diem) FROM diem; -- NULL bị bỏ qua khi tínhCASE: phân loại trong truy vấn
SELECT sv.ho_ten, d.diem,
CASE
WHEN d.diem IS NULL THEN 'Chưa có điểm'
WHEN d.diem >= 8.5 THEN 'Giỏi'
WHEN d.diem >= 7 THEN 'Khá'
WHEN d.diem >= 5 THEN 'Trung bình'
ELSE 'Không đạt'
END AS xep_loai
FROM diem d JOIN sinhvien sv ON sv.id = d.sinhvien_id;
-- Dạng ngắn khi so sánh bằng
SELECT ho_ten, CASE gioi_tinh WHEN 'Nam' THEN 'Anh' ELSE 'Chị' END AS xung_ho FROM sinhvien;
-- Sắp xếp theo thứ tự tùy ý
SELECT * FROM lop ORDER BY CASE khoa WHEN 'KHTN&CN' THEN 1 ELSE 2 END, ten_lop;Khi so sánh ngày, viết theo định dạng YYYY-MM-DD trong nháy đơn; MySQL tự hiểu là kiểu DATE.
NOT IN với danh sách có NULL (ví dụ từ truy vấn con) trả về rỗng: lọc IS NOT NULL trong truy vấn con hoặc dùng NOT EXISTS.
- Tìm sinh viên có họ Cầm hoặc Lường.
- Liệt kê sinh viên sinh trong quý 1 năm 2006.
- Liệt kê sinh viên chưa có email, hiển thị “chưa cập nhật” thay cho NULL.
- Xếp loại tất cả điểm bằng CASE và đếm số lượng mỗi loại (kết hợp GROUP BY ở bài 5).
- LIKE với % và _; REGEXP cho mẫu phức tạp.
- IN, BETWEEN gọn hơn nhiều OR/AND.
- NULL: dùng IS NULL, IFNULL, COALESCE.
- CASE WHEN phân loại và sắp xếp tùy ý.