- Thông thường, bài toán về phép chia có chứa từ khóa "tất cả" trong yêu cầu. Ví dụ: Tìm hóa đơn mua tất cả mặt hàng do Trung Quốc sản xuất; Cho biết sinh viên đăng kí tất cả các môn học,..."
- Khác với ngôn ngữ đại số quan hệ, ngôn ngữ SQL không hỗ trợ phép chia vì thế chúng ta phải thể hiện nó thông qua các toán tử: except, not exists, group by + having,...
Xét cơ sở dữ liệu quan hệ sau:
PHONGCHIEU (MaPC, TenPhong, SucChua, LoaiCN)
PHIM (MaPhim, TenPhim, ThoiLuong, NgayPhatHanh, DoanhThu)
THELOAI (MaTL, TenTL)
PHIM_THELOAI (MaPhim, MaTL)
SUATCHIEU (MaSC, MaPhim, NgayChieu, GioChieu, MaPC, TongTienVe)
--------------------
Cho biết những phim thuộc tất cả các thể loại?
-------------------
Cách 1: Thể hiện phép chia với NOT EXISTS - NOT EXISTS
Tạm dịch đề bài: Cho biết những Phim mà không có thể loại nào mà nó không thuộc vào?
Như vậy, sẽ liên quan tới 3 bảng PHIM, THE_LOAI và PHIM_THELOAI
+ Trả về bộ giá trị của bảng Phim nếu cả 2 điều kiện sau where cùng đúng
+ Bộ giá trị của câu truy vấn con trả về chính là những phim mà chưa có thể loại, nếu câu truy vấn con không trả về bộ giá trị nào thì có nghĩa là phim thuộc tất cả các thể loại
- EXISTS: trả về tất cả bản ghi nếu có ít nhất 1 bộ trong truy vấn con => có ít nhất 1 bộ mà nó thuộc vào (phim thuộc ít nhất 1 bản ghi trong thể loại)
- NOT EXISTS: trả về tất cả bản ghi nếu không có bộ nào trong truy vấn con => không có bộ nào mà nó không thuộc vào -> tất cả (phim thuộc tất cả bản ghi của thể loại)
/*** Giải thích: ***/
/*
- B1: Tìm danh sách thể loại không có trong PHIM_THELOAI
-> tức là thể loại đó chưa được làm phim
=> Dạng phép trừ sử dụng NOT EXIST
*/
select *
from THELOAI tl
where NOT EXISTS (
select *
from PHIM_THELOAI p_tl
where tl.MaTL = p_tl.MaTL
)
-- Những phim thuộc tất cả thể loại không nằm trong danh sách này
/* B2: Tìm danh sách phim không nằm trong danh sách đã trả về
- EXISTS: trả về tất cả bản ghi nếu có ít nhất 1 bộ trong truy vấn con
=> có ít nhất 1 bộ mà nó thuộc vào
(phim thuộc ít nhất 1 bản ghi trong thể loại)
- NOT EXISTS: trả về tất cả bản ghi nếu không có bộ nào trong truy vấn con
=> không có bộ nào mà nó không thuộc vào -> tất cả
(phim thuộc tất cả bản ghi của thể loại)
*/
Cách 2: Thể hiện phép chia với NOT EXISTS - EXCEPT
select *
from PHIM p
where NOT EXISTS (
(select tl.MaTL
from THELOAI tl)
except
(select p_tl.MaTL
from PHIM_THELOAI p_tl
where p.MaPhim = p_tl.MaPhim)
);
Cách 3: Thể hiện phép chia với GROUP BY + HAVING
Nếu không xét về hiệu suất thì cách tiếp cận này là đơn giản, dễ hiểu nhất!
-- B1: Đếm số thể loại
select count(MaTL) from THELOAI;
-- B2: Đếm MaTL theo MaPhim
select MaPhim
from PHIM_THELOAI
group by MaPhim
having COUNT(MaTL) >= all (
select count(MaTL)
from THELOAI
);
-- B3: Hiển thị đầy đủ thông tin của Phim
select *
from PHIM
where MaPhim IN (select MaPhim
from PHIM_THELOAI
group by MaPhim
having COUNT(MaTL) >= all
(
select count(MaTL)
from THELOAI
)
);
---
Link tải file SQL để import vào SQL server:
Nhận xét
Đăng nhận xét