Tags:

Truy vấn lồng | Truy vấn con trong sql

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ả
a b
1 2
1 6
2 3
2 7
3 4
4 5
Kết quả
a b
1 2
3 4
2 3
4 5
2 7
3 4
2 3
1 6

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

https://www.geeksforgeeks.org/sql-subquery/

2.3 8 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x