[Lưu Nhanh] Trọn Bộ 100+ Bài Tập SQL Từ Cơ Bản Đến Nâng Cao (Có Lời Giải Chi Tiết)
Phần 1: Truy vấn cơ bản (SELECT, FROM, WHERE, ORDER BY)
-- 1. Hiển thị tất cả nhân viên
SELECT * FROM tblEmployee;
-- 2. Hiển thị tất cả nhân viên có giới tính là nam
SELECT * FROM tblEmployee WHERE empSex = 'Nam' OR empSex = 'M';
-- 3. Hiển thị thông tin tất cả nhân viên nhưng chỉ lấy thông tin mã số, tên, địa chỉ và ngày bắt đầu đi làm
SELECT empSSN, empName, address, empStartDate FROM tblEmployee;
-- 4. Hiển thị thông tin nhân viên tương ứng (empSSN -> Mã NV, empName -> Tên NV)
SELECT empSSN AS N'Mã NV', empName AS N'Tên NV' FROM tblEmployee;
-- 5. Hiển thị 5 nhân viên đầu tiên các thông tin empSSN, empName đổi thành Tên nhân viên và empSex, address
SELECT TOP 5 empSSN, empName AS N'Tên nhân viên', empSex, address FROM tblEmployee;
-- 6. Lấy tất cả nhân viên có lương trên 3000 và là nữ
SELECT * FROM tblEmployee WHERE salary > 3000 AND (empSex = 'Nữ' OR empSex = 'F');
-- 8. Lấy tất cả nhân viên không có ngừoi quản lý
SELECT * FROM tblEmployee WHERE supervisorSSN IS NULL;
-- 9. Lấy tất cả nhân viên có chữ 'Hoàng'
SELECT * FROM tblEmployee WHERE empName LIKE N'%Hoàng%';
-- 10. Lấy tất cả nhân viên có tên lót là '' (Giả sử tên lót là khoảng trắng hoặc không có)
-- Lưu ý: Việc lấy tên lót phụ thuộc vào cách lưu trữ dữ liệu. Nếu gộp chung họ tên, câu này có thể dùng LIKE.
SELECT * FROM tblEmployee WHERE empName LIKE N'% % %';
-- 11. Liệt kê tên nhân viên, lương, ngày vào làm sau đó sắp xếp giảm dần theo ngày vào làm, biét rằng nhân viên phải là nữ
SELECT empName, salary, empStartDate
FROM tblEmployee
WHERE empSex = N'Nữ'
ORDER BY empStartDate DESC;
-- 12. Mã số, họ tên, giới tính, lương, ngày làm việc theo thứ tự ngày làm việc giảm dần
SELECT empSSN, empName, empSex, salary, empStartDate
FROM tblEmployee
ORDER BY empStartDate DESC;
-- 13. [Thiếu thông tin cột tăng dần] Giả sử: Sắp xếp theo Lương tăng dần và ngày làm việc giảm dần
SELECT * FROM tblEmployee ORDER BY salary ASC, empStartDate DESC;
-- 14. Hiển thị 10 nhân viên với mã số, họ tên, lương, ngày sinh, địa chỉ
SELECT TOP 10 empSSN, empName, salary, empBirthdate, address FROM tblEmployee;
-- 15. Những nhân viên không có người quản lý, họ Nguyễn và ở TP.HCM
SELECT * FROM tblEmployee
WHERE supervisorSSN IS NULL AND empName LIKE N'Nguyễn%' AND address LIKE N'%TP.HCM%';
-- 16. Những nhân viên có người quản lý, lương > 10000 và ở TP.HCM
SELECT * FROM tblEmployee
WHERE supervisorSSN IS NOT NULL AND salary > 10000 AND address LIKE N'%TP.HCM%';
-- 17. Như câu 16, sắp xếp tăng dần theo ngày vào làm và giảm dần theo lương
SELECT * FROM tblEmployee
WHERE supervisorSSN IS NOT NULL AND salary > 10000 AND address LIKE N'%TP.HCM%'
ORDER BY empStartDate ASC, salary DESC;
-- 18. Mã số, họ tên, giới tính, lương, ngày làm việc; lương > 30000; sắp xếp ngày sinh giảm dần, ngày vào làm tăng dần
SELECT empSSN, empName, empSex, salary, empStartDate
FROM tblEmployee
WHERE salary > 30000
ORDER BY empBirthdate DESC, empStartDate ASC;
-- 19. Thông tin nhân viên có tên Giang và là nữ
SELECT * FROM tblEmployee WHERE empName LIKE N'%Giang' AND empSex = N'Nữ';
-- 20. Nhân viên có họ Vũ, là nữ, ở HCM hoặc HN
SELECT * FROM tblEmployee
WHERE empName LIKE N'Vũ%' AND empSex = N'Nữ'
AND (address LIKE N'%HCM%' OR address LIKE N'%HN%');
-- 21. Nhân viên có chữ lót là Hồng
SELECT * FROM tblEmployee WHERE empName LIKE N'% Hồng %';
Phần 2: Các hàm phổ biến nâng cao & Truy vấn lồng
-- 22. Thông tin nhân viên sinh tháng 2
SELECT * FROM tblEmployee WHERE MONTH(empBirthdate) = 2;
-- 23. Mã nhân viên, tên nhân viên và tháng sinh
SELECT empSSN, empName, MONTH(empBirthdate) AS ThangSinh FROM tblEmployee;
-- 24. Tháng sinh lớn hơn 4
SELECT * FROM tblEmployee WHERE MONTH(empBirthdate) > 4;
-- 25. Mã nv, tên nv, tháng sinh, điều kiện tháng sinh > 4 và sắp xếp giảm dần theo tháng
SELECT empSSN, empName, MONTH(empBirthdate) AS ThangSinh
FROM tblEmployee
WHERE MONTH(empBirthdate) > 4
ORDER BY ThangSinh DESC;
-- 26. Nhân viên làm việc tại các tháng lẻ (Tháng bắt đầu đi làm)
SELECT * FROM tblEmployee WHERE MONTH(empStartDate) % 2 <> 0;
-- 27. Nhân viên có mã phòng ban là chẵn
SELECT * FROM tblEmployee WHERE depNum % 2 = 0;
-- 28. Hiển thị thông tin riêng biệt của nhân viên (Dùng DISTINCT cho một cột cụ thể, ví dụ phòng ban)
SELECT DISTINCT depNum FROM tblEmployee;
-- 29. Nhân viên có tuổi lớn hơn 40
SELECT * FROM tblEmployee WHERE YEAR(GETDATE()) - YEAR(empBirthdate) > 40;
-- 30. Liệt kê các mã nhân viên và quản lý
SELECT empSSN, supervisorSSN FROM tblEmployee;
------- TRUY VẤN LỒNG (QUAN TRỌNG) --------
-- 31. Tên những nhân viên là quản lý của nhân viên khác
SELECT empName FROM tblEmployee
WHERE empSSN IN (SELECT DISTINCT supervisorSSN FROM tblEmployee WHERE supervisorSSN IS NOT NULL);
-- 32. MS, tên, giới tính, địa chỉ của các nhân viên là quản lý của phòng ban
SELECT empSSN, empName, empSex, address
FROM tblEmployee
WHERE empSSN IN (SELECT mgrSSN FROM tblDepartment);
-- 33. Quản lý phòng ban VÀ đang quản lý nhân viên khác
SELECT empSSN, empName, empSex, address
FROM tblEmployee
WHERE empSSN IN (SELECT mgrSSN FROM tblDepartment)
AND empSSN IN (SELECT supervisorSSN FROM tblEmployee);
-- 34. Liệt kê những nhân viên có người thân
SELECT * FROM tblEmployee WHERE empSSN IN (SELECT empSSN FROM tblDependent);
-- 35. Liệt kê những nhân viên có tham gia làm dự án
SELECT * FROM tblEmployee WHERE empSSN IN (SELECT empSSN FROM tblWorksOn);
-- 36. Liệt kê những địa điểm đặt phòng ban
SELECT * FROM tblLocation WHERE locNum IN (SELECT locNum FROM tblDepLoc);
-- 37. Liệt kê những phòng ban có tham gia dự án
SELECT * FROM tblDepartment WHERE depNum IN (SELECT depNum FROM tblProject);
-- 38. Nhân viên tham gia dự án VÀ làm quản lý phòng ban
SELECT * FROM tblEmployee
WHERE empSSN IN (SELECT empSSN FROM tblWorksOn)
AND empSSN IN (SELECT mgrSSN FROM tblDepartment);
-- 39. Nhân viên đang làm quản lý phòng ban
SELECT * FROM tblEmployee WHERE empSSN IN (SELECT mgrSSN FROM tblDepartment);
------- BÀI LUYỆN TẬP --------
-- 40. Nhân viên có tháng sinh là chẵn
SELECT * FROM tblEmployee WHERE MONTH(empBirthdate) % 2 = 0;
-- 41. Tháng sinh chẵn, giảm dần theo năm sinh
SELECT * FROM tblEmployee
WHERE MONTH(empBirthdate) % 2 = 0
ORDER BY YEAR(empBirthdate) DESC;
-- 42. Mã nv, tên nv, ngày sinh, tháng sinh, và năm sinh > 1965
SELECT empSSN, empName, DAY(empBirthdate) AS Ngay, MONTH(empBirthdate) AS Thang, YEAR(empBirthdate) AS Nam
FROM tblEmployee
WHERE YEAR(empBirthdate) > 1965;
-- 43. Tên, mã NV, số năm đi làm, tuổi. Ở TP.HCM hoặc Hà Nội
SELECT empName, empSSN,
YEAR(GETDATE()) - YEAR(empStartDate) AS SoNamDiLam,
YEAR(GETDATE()) - YEAR(empBirthdate) AS Tuoi
FROM tblEmployee
WHERE address LIKE N'%TP.HCM%' OR address LIKE N'%Hà Nội%';
-- 44, 45, 46. (Kết hợp logic tính toán thời gian và sắp xếp)
SELECT empSSN, empName, salary,
YEAR(GETDATE()) - YEAR(empStartDate) AS SoNamDiLam,
YEAR(GETDATE()) - YEAR(empBirthdate) AS Tuoi
FROM tblEmployee
WHERE (address LIKE N'%TP.HCM%' OR address LIKE N'%Hà Nội%')
ORDER BY SoNamDiLam ASC, Tuoi DESC;
-- 47, 48, 49, 50. (Truy vấn lồng với các điều kiện phức tạp)
-- Lấy ví dụ câu 49:
SELECT empSSN, empName, salary,
YEAR(GETDATE()) - YEAR(empBirthdate) AS Tuoi,
YEAR(GETDATE()) - YEAR(empStartDate) AS SoNamDiLam
FROM tblEmployee E1
WHERE EXISTS (
SELECT 1 FROM tblEmployee E2
WHERE E1.supervisorSSN = E2.empSSN
AND E2.empSex = 'Nam'
)
AND salary > 10000
AND (YEAR(GETDATE()) - YEAR(empStartDate)) < 10
AND (YEAR(GETDATE()) - YEAR(empBirthdate)) > 40
ORDER BY salary ASC, SoNamDiLam DESC;
Phần 3: Hàm tổng hợp (COUNT, SUM, MAX, MIN)
-- 51. Đếm số lượng nhân viên
SELECT COUNT(*) AS SoLuongNV FROM tblEmployee;
-- 52. Bao nhiêu nhân viên lương > 30000
SELECT COUNT(*) FROM tblEmployee WHERE salary > 30000;
-- 53. Bao nhiêu nhân viên là quản lý nhân viên khác
SELECT COUNT(DISTINCT supervisorSSN) FROM tblEmployee WHERE supervisorSSN IS NOT NULL;
-- 54. Lương nhỏ nhất
SELECT MIN(salary) AS LuongNhoNhat FROM tblEmployee;
-- 55. Bảng tổng hợp
SELECT COUNT(*) AS SLNV, MIN(salary) AS LuongMin, MAX(salary) AS LuongMax,
AVG(salary) AS LuongTB, SUM(salary) AS TongLuong
FROM tblEmployee;
-- 56. Có bao nhiêu loại giới tính
SELECT COUNT(DISTINCT empSex) FROM tblEmployee;
-- 59. Tổng lương công ty phải trả hàng tháng
SELECT SUM(salary) FROM tblEmployee;
-- 60. Đếm số lượng nhân viên không có quản lý
SELECT COUNT(*) FROM tblEmployee WHERE supervisorSSN IS NULL;
-- 61. Tổng lương phải trả cho giám sát (nhân viên có quản lý người khác)
SELECT SUM(salary) FROM tblEmployee
WHERE empSSN IN (SELECT DISTINCT supervisorSSN FROM tblEmployee);
-- 62. Tuổi trung bình của quản lý phòng ban
SELECT AVG(YEAR(GETDATE()) - YEAR(empBirthdate))
FROM tblEmployee
WHERE empSSN IN (SELECT mgrSSN FROM tblDepartment);
Phần 4 & 5: Gom nhóm (GROUP BY) & Truy vấn lồng/JOIN nâng cao
-- 63 & 64. Bao nhiêu nhân viên mỗi phòng ban (Hiển thị mã phòng ban)
SELECT depNum, COUNT(*) AS SoLuongNV FROM tblEmployee GROUP BY depNum;
-- 65. Thống kê theo phòng ban
SELECT depNum, COUNT(*) AS SLNV, MIN(salary) AS L_Min, MAX(salary) AS L_Max,
AVG(salary) AS L_Avg, SUM(salary) AS L_Sum
FROM tblEmployee
GROUP BY depNum;
-- 66. Thống kê theo phòng ban, chỉ lấy nhóm có > 4 nhân viên (Dùng HAVING)
SELECT depNum, COUNT(*) AS SLNV, MIN(salary) AS L_Min, MAX(salary) AS L_Max,
AVG(salary) AS L_Avg, SUM(salary) AS L_Sum
FROM tblEmployee
GROUP BY depNum
HAVING COUNT(*) > 4;
-- 68. Mỗi mã nhân viên có bao nhiêu thân nhân
SELECT empSSN, COUNT(*) AS SoThanNhan FROM tblDependent GROUP BY empSSN;
-- 69. Mỗi nhân viên làm trên bao nhiêu dự án
SELECT empSSN, COUNT(proNum) AS SoDuAn FROM tblWorksOn GROUP BY empSSN;
-- 78. Liệt kê phòng ban, lương trung bình của phòng ban lớn hơn lương trung bình công ty
SELECT depNum, AVG(salary) AS LuongTB_Phong
FROM tblEmployee
GROUP BY depNum
HAVING AVG(salary) > (SELECT AVG(salary) FROM tblEmployee)
ORDER BY LuongTB_Phong ASC;
-- 82. Hiển thị tên NV, tên phòng ban đang làm việc (Sử dụng JOIN)
SELECT e.empName, d.depName
FROM tblEmployee e
INNER JOIN tblDepartment d ON e.depNum = d.depNum;
-- 83. Liệt kê tên nhân viên, tên thân nhân và mối quan hệ
SELECT e.empName, d.depName AS TenThanNhan, d.depRelationship
FROM tblEmployee e
INNER JOIN tblDependent d ON e.empSSN = d.empSSN;
-- 87. Tên phòng ban, các dự án do phòng quản lý và địa điểm
SELECT d.depName, p.proName, l.locName
FROM tblDepartment d
INNER JOIN tblProject p ON d.depNum = p.depNum
INNER JOIN tblLocation l ON p.locNum = l.locNum;
-- 89. Tên dự án, tên nhân viên tham gia và phòng ban NV đó làm
SELECT p.proName, e.empName, d.depName
FROM tblWorksOn w
INNER JOIN tblProject p ON w.proNum = p.proNum
INNER JOIN tblEmployee e ON w.empSSN = e.empSSN
INNER JOIN tblDepartment d ON e.depNum = d.depNum;
-- 92. Tên nhân viên và quản lý của nhân viên đó (Self Join)
SELECT e1.empName AS NhanVien, e2.empName AS QuanLy
FROM tblEmployee e1
LEFT JOIN tblEmployee e2 ON e1.supervisorSSN = e2.empSSN;
-- 98. Tên nhân viên, tên phòng ban mà NV đó không tham gia dự án nào
SELECT e.empName, d.depName
FROM tblEmployee e
INNER JOIN tblDepartment d ON e.depNum = d.depNum
WHERE e.empSSN NOT IN (SELECT empSSN FROM tblWorksOn);
-- 106. Tên nhân viên và số lượng dự án nhân viên tham gia
SELECT e.empName, COUNT(w.proNum) AS SoLuongDuAn
FROM tblEmployee e
LEFT JOIN tblWorksOn w ON e.empSSN = w.empSSN
GROUP BY e.empSSN, e.empName;
-- 107. Tên dự án và số lượng nhân viên tham gia
SELECT p.proName, COUNT(w.empSSN) AS SoLuongNhanVien
FROM tblProject p
LEFT JOIN tblWorksOn w ON p.proNum = w.proNum
GROUP BY p.proNum, p.proName;
All rights reserved