SQL là một ngôn ngữ lập trình dùng để truy vấn và quản lý cơ sở dữ liệu. Trong SQL, truy vấn lồng là một câu truy vấn được viết bên trong một câu truy vấn khác. Câu truy vấn con này được thực hiện trong ngữ cảnh của câu truy vấn chính.
Các quy tắc về truy vấn con
Các truy vấn con trong SQL phải tuân thủ các quy tắc sau:
- Câu truy vấn con có thể được đặt trong mệnh đề WHERE, HAVING và FROM của câu truy vấn chính.
- Truy vấn con có thể được sử dụng với các câu lệnh SELECT, UPDATE, INSERT, DELETE cùng với các toán tử biểu thức như =, >, <, <= và toán tử Like.
- Các truy vấn con phải được bao trong dấu ngoặc đơn ().
- Câu lệnh ORDER BY không thể được sử dụng trong một truy vấn con, nhưng có thể sử dụng GROUP BY để thực hiện chức năng tương tự như ORDER BY trong một truy vấn con.
- Các truy vấn con, mà trả về nhiều hơn một hàng, chỉ có thể được sử dụng với các toán tử nhân như toán tử IN.
- Danh sách trong câu lệnh SELECT không thể bao gồm bất kỳ tham chiếu nào tới các giá trị đánh giá một BLOB, ARRAY, CLOB hoặc NCLOB.
- Một truy vấn con không thể bị bao quanh trong một hàm tập hợp.
- Toán tử BETWEEN không thể được sử dụng với một truy vấn con, nhưng có thể sử dụng bên trong truy vấn con.
Cách viết truy vấn lồng
Dưới đây là cách viết truy vấn lồng trong một số trường hợp cụ thể:
Các phép toán tập hợp
Phép trừ
Phép trừ trong SQL được thực hiện bằng cách sử dụng toán tử EXCEPT hoặc truy vấn lồng với NOT EXISTS hoặc NOT IN. Ví dụ: Tìm các giáo viên không tham gia vào bất kỳ đề tài nào.
Sử dụng EXCEPT
- Đơn giản: Chỉ trả về thông tin MAGV
SELECT MAGV FROM GIAOVIEN GV EXCEPT SELECT MAGV FROM THAMGIADT TG
- Phức tạp: Trả về thông tin MAGV và HOTEN
SELECT MAGV, HOTEN FROM GIAOVIEN GV EXCEPT SELECT GV.MAGV, GV.HOTEN FROM THAMGIADT TG, GIAOVIEN GV WHERE TG.MAGV = GV.MAGV
Sử dụng NOT EXISTS
SELECT GV.MAGV, GV.HOTEN FROM GIAOVIEN GV WHERE NOT EXISTS ( SELECT * FROM THAMGIADT TG WHERE TG.MAGV = GV.MAGV)
Sử dụng NOT IN
SELECT MAGV, HOTEN FROM GIAOVIEN WHERE MAGV NOT IN (SELECT MAGV FROM THAMGIADT)
Phép giao
Phép giao trong SQL được thực hiện bằng cách sử dụng toán tử INTERSECT hoặc truy vấn lồng với EXISTS hoặc IN hoặc sử dụng phép kết thông thường. Ví dụ: Tìm các giáo viên vừa tham gia đề tài vừa là trưởng bộ môn.
Sử dụng INTERSECT
SELECT TRUONGBM FROM BOMON INTERSECT SELECT MAGV FROM THAMGIADT
Sử dụng ... IN (...) AND ... IN (...)
SELECT GV.MAGV, GV.HOTEN FROM GIAOVIEN GV WHERE MAGV IN (SELECT TRUONGBM FROM BOMON) AND MAGV IN (SELECT MAGV FROM THAMGIADT)
Sử dụng EXISTS (...) AND EXISTS (...)
SELECT GV.MAGV, GV.HOTEN FROM GIAOVIEN GV WHERE EXISTS (SELECT * FROM BOMON WHERE TRUONGBM=GV.MAGV) AND EXISTS (SELECT * FROM THAMGIADT TG WHERE TG.MAGV = GV.MAGV)
Sử dụng phép kết thông thường
SELECT TG.MAGV FROM BOMON BM, THAMGIADT TG WHERE BM.TRUONGBM = TG.MAGV
Phép hội
Phép hội trong SQL được thực hiện bằng cách sử dụng toán tử UNION (các dòng trùng lắp sẽ được bỏ đi) hoặc UNION ALL (lấy tất cả các dòng của các bảng) hoặc truy vấn lồng với EXISTS hoặc IN. Điều kiện để thực hiện UNION / INTERSECT, EXCEPT là các bảng phải có cùng số lượng thuộc tính và tương ứng kiểu dữ liệu giữa các cột. Các cột của bảng kết xuất chính là các cột trong bảng đầu tiên.
UNION SELECT * FROM TABLE1 UNION ALL SELECT * FROM TABLE2 SELECT * FROM TABLE1 UNION ALL SELECT * FROM TABLE2
Ví dụ: Liệt kê những giáo viên có tham gia đề tài và những giáo viên là trưởng bộ môn.
Sử dụng UNION:
SELECT MAGV FROM THAMGIADT UNION SELECT TRUONGBM FROM BOMON
Sử dụng EXISTS (…) OR EXISTS (…)
SELECT GV.MAGV, GV.HOTEN FROM GIAOVIEN GV WHERE EXISTS ( SELECT * FROM BOMON WHERE TRUONGBM=GV.MAGV) OR EXISTS ( SELECT * FROM THAMGIADT TG WHERE TG.MAGV = GV.MAGV)
Sử dụng IN (…) OR IN (…)
SELECT GV.MAGV, GV.HOTEN FROM GIAOVIEN GV WHERE GV.MAGV IN (SELECT TRUONGBM FROM BOMON ) OR GV.MAGV IN ( SELECT MAGV FROM THAMGIADT TG )
Phép chia
Phép chia trong SQL được thực hiện bằng cách sử dụng toán tử DIVISION hoặc truy vấn lồng với EXISTS. Để thực hiện phép chia, hai bảng phải có cùng số lượng thuộc tính và tương ứng kiểu dữ liệu giữa các cột. Các cột của bảng kết xuất chính là các cột trong bảng đầu tiên.
Sử dụng EXCEPT
SELECT R1.A, R1.B, R1.C FROM R R1 WHERE NOT EXISTS ( ( SELECT S.D, S.E FROM S) EXCEPT ( SELECT R2.D, R2.E FROM R R2 WHERE R1.A=R2.A AND R1.B=R2.B AND R1.C=R2.C ) )
Sử dụng NOT EXISTS
SELECT R1.A, R1.B, R1.C FROM R R1 WHERE NOT EXISTS ( SELECT * FROM S WHERE NOT EXISTS ( SELECT * FROM R R2 WHERE R2.D=S.D AND R2.E=S.E AND R1.A=R2.A AND R1.B=R2.B AND R1.C=R2.C ))
Ví dụ: Tìm các giáo viên (MAGV) mà tham gia tất cả các đề tài
Bị chia: THAMGIADT (MAGV, MADT, …) Chia: DETAI (MADT, …)
SELECT DISTINCT TG1.MAGV FROM THAMGIADT TG1 WHERE NOT EXISTS ( ( SELECT MADT FROM DETAI) EXCEPT ( SELECT MADT FROM THAMGIADT TG2 WHERE TG2.MAGV = TG1.MAGV ) )
Sử dụng Gom nhóm
Có thể sử dụng Gom nhóm trong SQL để nhóm các kết quả trả về dựa trên một số tiêu chí. Ví dụ: Tìm tên các giáo viên thuộc bộ môn "HTTT" mà tham gia vào tất cả các đề tài của chủ đề "QLGD".
SELECT GV.MAGV, GV.HOTEN FROM GIAOVIEN GV WHERE GV.MABM='HTTT' AND GV.MAGV IN ( SELECT TG.MAGV FROM THAMGIADT TG WHERE TG.MADT IN ( SELECT MADT FROM DETAI WHERE MACD='QLGD' ) ) GROUP BY GV.MAGV, GV.HOTEN HAVING COUNT(DISTINCT TG.MADT) = ( SELECT COUNT(MADT) FROM DETAI WHERE MACD='QLGD' )
Nguồn tham khảo: GeeksforGeeks