Mục lục
Trong SQL truy vấn lồng là một câu truy vấn được định nghĩa bên trong một câu truy vấn khác. Câu truy vấn được đặt bên trong một câu truy vấn khác được gọi là câu truy vấn con.
Các truy vấn con phải tuân theo các quy tắc sau:
- Bạn có thể đặt câu truy vấn con trong các mệnh đề WHERE, HAVING và FROM của câu truy vấn cha(câu truy vấn bên ngoài).
- 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 toán tử biểu thức. Nó có thể là toán tử bình đẳng hoặc toán tử so sánh như =,>, =, <= và toán tử Like.
- Các truy vấn con phải được bao trong các 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, mặc dù truy vấn chính có thể sử dụng một ORDER BY. GROUP BY có thể được sử dụng để thực hiện cùng tính năng 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, có thể chỉ được sử dụng với các toán tử nhân, ví dụ: toán tử IN.
- Danh sách của SELECT không thể bao gồm bất kỳ tham chiếu nào tới các giá trị mà ước lượng một BLOB, ARRAY, CLOB hoặc NCLOB.
- Một truy vấn con không thể bị bao quanh một cách trực tiếp 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; tuy nhiên, toán tử BETWEEN có thể được sử dụng bên trong truy vấn con.
Cách viết truy lồng
Cho lược đồ cơ sở dữ liệu QUANLYDETAI sau:
Mặc dù không có một cú pháp chung cho việc viết câu truy vấn lồng, dưới đây mình sẽ liệt kê cách viết truy vấn lồng trong các trường hợp cụ thể sau:
Các phép toán tập hợp
Phép trừ
Cách làm:
– Sử dụng toán tử EXCEPT
– 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 đề tài nào.
Nhận xét: Nhân viên không tham gia đề án = Tất cả giáo viên – Các giáo viên có
tham gia đề án.
Sử dụng EXCEPT
-- Đơn giản: CHỉ cho biết thông tin MAGV SELECT MAGV FROM GIAOVIEN GV EXCEPT SELECT MAGV FROM THAMGIADT TG -- Phức tạp: Cho biết 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
Cách làm:
– Sử dụng toán tử INTERSECT
– Truy vấn lồng với EXISTS hoặc IN
– 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.
– Nhận xét: Kết quả =Giáo viên có tham gia đề tài ∩ Giáo viên 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
Cách làm:
– Sử dụng toán tử UNION (Các dòng trùng lắp sẽ được bỏ đi) / UNION ALL
(Lấy tất cả các dòng của các bảng)
– Truy vấn lồng với EXISTS hoặc IN
Điều kiện để thực hiện được UNION / INTERSECT, EXCEPT : 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 | UNION ALL | ||||||||||||||||||||||||||||||||
SELECT * FROM TABLE1 UNION SELECT * FROM TABLE2 |
SELECT * FROM TABLE1 UNION ALL SELECT * FROM TABLE2 |
||||||||||||||||||||||||||||||||
Kết quả
|
Kết quả
|
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
Cho các bảng R (A, B, C, D, E) và S (D, E) như sau:
Bị chia: R
Chia: S
Sử dụng EXCEPT
Cú pháp:
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 ) )
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 NOT EXISTS
Cú pháp:
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 (Dùng NOT
EXISTS)
Bị chia : THAMGIADT (MAGV, MADT, …)
Chia: DETAI (MADT, …)
SELECT TG.MAGV FROM THAMGIADT TG1 WHERE NOT EXISTS ( SELECT * FROM DETAI DT WHERE NOT EXISTS ( SELECT * FROM THAMGIADT TG2 WHERE TG2.MADT=DT.MADT AND TG2.MAGV=TG1.MAGV ))
Sử dụng Gom nhóm
Cho R(A,B), S(B), thực hiện R÷S
SELECT R.A FROM R [WHERE R.B IN (SELECT S.B FROM S [WHERE <ĐK>]] GROUP BY R.A HAVING COUNT(DISTINCT R.B) = ( SELECT COUNT(S.B) FROM S [WHERE <ĐK>])
Ví dụ: Tìm các giáo viên (MAGV) mà tham gia tất cả các đề tài (Dùng NOT
EXISTS)
Bị chia : THAMGIADT (MAGV, MADT, STT, …)
Chia: DETAI (MADT, …)
SELECT TG.MAGV FROM THAMGIADT TG1 GROUP BY TG.MAGV HAVING COUNT(DISTINCT TG1.MADT) = ( SELECT COUNT(DT.MADT) FROM DETAI DT )
Một số ví dụ khác
Tìm tên các giáo viên ‘HTTT’ mà tham gia tất cả các đề tài thuộc chủ đề
‘QLGD’
-- EXCEPT SELECT DISTINCT TG1.MAGV, GV.HOTEN FROM THAMGIADT TG1, GIAOVIEN GV WHERE TG1.MAGV=GV.MAGV AND GV.MABM=’HTTT’ AND NOT EXISTS ( ( SELECT MADT FROM DETAI WHERE MACD=’QLGD’) EXCEPT ( SELECT MADT FROM THAMGIADT TG2 WHERE TG2.MAGV = TG1.MAGV ) ) -- NOT EXISTS SELECT TG1.MAGV, GV.HOTEN FROM THAMGIADT TG1, GIAOVIEN GV WHERE TG1.MAGV=GV.MAGV AND GV.MABM=’HTTT’ AND NOT EXISTS ( SELECT * FROM DETAI DT WHERE MACD=’QLGD’ AND NOT EXISTS ( SELECT * FROM THAMGIADT TG2 WHERE TG2.MADT=DT.MADT AND TG2.MAGV=TG1.MAGV )) -- COUNT SELECT TG1.MAGV , GV.HOTEN FROM THAMGIADT TG1 , GIAOVIEN GV WHERE TG1.MAGV=GV.MAGV AND GV.MABM=’HTTT’ AND TG1.MADT IN (SELECT MADT FROM DETAI WHERE MACD=’QLGD’) GROUP BY TG1.MAGV , GV.HOTEN HAVING COUNT(DISTINCT TG1.MADT) = ( SELECT COUNT(MADT) FROM DETAI WHERE MACD=’QLGD’ )
Nguồn tham khảo