Bài tập & đáp án
Đề bài đọc tự do. Phần đáp án và giải thích chi tiết chỉ dành cho sinh viên đang học lớp thực hành IT004, cần mã truy cập từ giảng viên.
ĐỀ BÀI
Yêu cầu thực hành - Quản lý hàng hóa (36 câu)
Bài ôn tập tổng hợp dùng lược đồ cổ điển "Nhà cung cấp - Phụ tùng - Vận chuyển" (Suppliers - Parts - Shipments) rất hay gặp trong các đề thi và giáo trình CSDL. Sinh viên thực hiện lần lượt 36 câu sau:
NHACUNGCAP (MANCC, TENNCC, TRANGTHAI, THANHPHO)
Tân từ: "Nhà cung cấp" cung cấp các dịch vụ vận chuyển - Mã nhà cung cấp, tên nhà cung cấp, trạng thái và thành phố.
| Thuộc tính | Kiểu dữ liệu | Diễn giải |
|---|---|---|
MANCC | varchar(5) | Mã nhà cung cấp - Khóa chính |
TENNCC | varchar(20) | Tên nhà cung cấp |
TRANGTHAI | numeric(2) | Trạng thái (điểm xếp hạng nhà cung cấp) |
THANHPHO | varchar(30) | Thành phố |
PHUTUNG (MAPT, TENPT, MAUSAC, KHOILUONG, THANHPHO)
Tân từ: Thông tin phụ tùng gồm mã phụ tùng, tên phụ tùng, màu sắc, khối lượng và thành phố.
| Thuộc tính | Kiểu dữ liệu | Diễn giải |
|---|---|---|
MAPT | varchar(5) | Mã phụ tùng - Khóa chính |
TENPT | varchar(10) | Tên phụ tùng |
MAUSAC | varchar(10) | Màu sắc |
KHOILUONG | float | Khối lượng |
THANHPHO | varchar(30) | Thành phố |
VANCHUYEN (MANCC, MAPT, SOLUONG)
Tân từ: Lưu trữ thông tin nhà cung cấp dịch vụ vận chuyển những phụ tùng nào, số lượng là bao nhiêu.
| Thuộc tính | Kiểu dữ liệu | Diễn giải |
|---|---|---|
MANCC | varchar(5) | Mã nhà cung cấp - Khóa chính, khóa ngoại đến NHACUNGCAP |
MAPT | varchar(5) | Mã phụ tùng - Khóa chính, khóa ngoại đến PHUTUNG |
SOLUONG | numeric(5) | Số lượng phụ tùng đã vận chuyển |
Sơ đồ quan hệ
NHACUNGCAP (1) ➜ VANCHUYEN (N): Một nhà cung cấp có thể vận chuyển nhiều dòng phụ tùng khác nhau.
PHUTUNG (1) ➜ VANCHUYEN (N): Một phụ tùng có thể được nhiều nhà cung cấp vận chuyển.
- Hiển thị thông tin (MANCC, TENNCC, THANHPHO) của tất cả nhà cung cấp.
- Hiển thị thông tin của tất cả các phụ tùng.
- Hiển thị thông tin các nhà cung cấp ở thành phố London.
- Hiển thị mã phụ tùng, tên và màu sắc của tất cả các phụ tùng ở thành phố Paris.
- Hiển thị mã phụ tùng, tên, khối lượng của những phụ tùng có khối lượng lớn hơn 15.
- Tìm những phụ tùng (MAPT, TENPT, MAUSAC) có khối lượng lớn hơn 15, không phải màu đỏ (red).
- Tìm những phụ tùng (MAPT, TENPT, MAUSAC) có khối lượng lớn hơn 15, màu sắc khác màu đỏ (red) và xanh (green).
- Hiển thị những phụ tùng (MAPT, TENPT, khối lượng) có khối lượng lớn hơn 15 và nhỏ hơn 20, sắp xếp theo tên phụ tùng.
- Hiển thị những phụ tùng được vận chuyển bởi nhà cung cấp có mã số S1. Không hiển thị kết quả trùng (sử dụng phép kết).
- Hiển thị những nhà cung cấp vận chuyển phụ tùng có mã là P1 (sử dụng phép kết).
- Hiển thị thông tin nhà cung cấp ở thành phố London và có vận chuyển phụ tùng của thành phố London. Không hiển thị kết quả trùng (sử dụng phép kết).
- Lặp lại câu 9 nhưng sử dụng toán tử IN.
- Lặp lại câu 10 nhưng sử dụng toán tử IN.
- Lặp lại câu 9 nhưng sử dụng toán tử EXISTS.
- Lặp lại câu 10 nhưng sử dụng toán tử EXISTS.
- Lặp lại câu 11 nhưng sử dụng truy vấn con, dùng toán tử IN.
- Lặp lại câu 11 nhưng dùng truy vấn con, sử dụng toán tử EXISTS.
- Tìm nhà cung cấp chưa vận chuyển bất kỳ phụ tùng nào. Sử dụng NOT IN.
- Tìm nhà cung cấp chưa vận chuyển bất kỳ phụ tùng nào. Sử dụng NOT EXISTS.
- Tìm nhà cung cấp chưa vận chuyển bất kỳ phụ tùng nào. Sử dụng outer JOIN (phép kết ngoài).
- Có tất cả bao nhiêu nhà cung cấp?
- Có tất cả bao nhiêu nhà cung cấp ở London?
- Hiển thị trị giá cao nhất, thấp nhất của TRANGTHAI của các nhà cung cấp.
- Hiển thị giá trị cao nhất, thấp nhất của TRANGTHAI trong bảng NHACUNGCAP ở thành phố London.
- Mỗi nhà cung cấp vận chuyển bao nhiêu phụ tùng? Chỉ hiển thị mã nhà cung cấp, tổng số phụ tùng đã vận chuyển.
- Mỗi nhà cung cấp vận chuyển bao nhiêu phụ tùng? Hiển thị mã nhà cung cấp, tên, thành phố của nhà cung cấp và tổng số phụ tùng đã vận chuyển.
- Nhà cung cấp nào đã vận chuyển tổng cộng nhiều hơn 500 phụ tùng? Chỉ hiển thị mã nhà cung cấp.
- Nhà cung cấp nào đã vận chuyển nhiều hơn 300 phụ tùng màu đỏ (red)? Chỉ hiển thị mã nhà cung cấp.
- Nhà cung cấp nào đã vận chuyển nhiều hơn 300 phụ tùng màu đỏ (red)? Hiển thị mã nhà cung cấp, tên, thành phố và số lượng phụ tùng màu đỏ đã vận chuyển.
- Có bao nhiêu nhà cung cấp ở mỗi thành phố.
- Nhà cung cấp nào đã vận chuyển nhiều phụ tùng nhất? Hiển thị tên nhà cung cấp và số lượng phụ tùng đã vận chuyển.
- Thành phố nào có cả nhà cung cấp và phụ tùng.
- Viết câu lệnh SQL để insert nhà cung cấp mới: S6, Duncan, 30, Paris.
- Viết câu lệnh SQL để thay đổi thành phố của S6 (ở câu 33) thành Sydney.
- Viết câu lệnh SQL tăng TRANGTHAI của nhà cung cấp ở London lên thêm 10.
- Viết câu lệnh SQL xóa nhà cung cấp S6.
ĐÁP ÁN
Xem đáp án
Nội dung được bảo vệ
Nhập mã truy cập để xem đáp án Tuần 6.
Mã truy cập được cung cấp bởi giảng viên.
Đáp án đầy đủ cho 36 câu. Đây là lược đồ kinh điển "Suppliers - Parts - Shipments" nên nhiều câu (9-17, 18-20) cố ý lặp lại cùng 1 yêu cầu bằng nhiều kỹ thuật khác nhau (JOIN, IN, EXISTS, subquery, outer JOIN) - Đúng ý đồ của đề là để so sánh trực tiếp các cách viết tương đương nhau, không phải làm dư thừa. Gõ lại từng câu vào SSMS để nhớ lâu hơn nhé - Nút Copy ở đây chỉ mang tính hình thức thôi.
CÂU 1 · SELECT
Đề bài: Hiển thị thông tin (MANCC, TENNCC, THANHPHO) của tất cả nhà cung cấp.
SELECT MANCC, TENNCC, THANHPHO
FROM NHACUNGCAP;SELECT liệt kê đúng 3 cột đề yêu cầu, không dùng SELECT *.
Đề chỉ định rõ 3 cột trong ngoặc (MANCC, TENNCC, THANHPHO) - Không lấy thêm cột TRANGTHAI dù bảng có sẵn.
CÂU 2 · SELECT *
Đề bài: Hiển thị thông tin của tất cả các phụ tùng.
SELECT *
FROM PHUTUNG;SELECT * lấy toàn bộ cột hiện có trong PHUTUNG.
Đề chỉ nói "thông tin" chung chung, không liệt kê cột cụ thể như Câu 1 - Nên lấy tất cả là hợp lý nhất.
CÂU 3 · WHERE
Đề bài: Hiển thị thông tin các nhà cung cấp ở thành phố London.
SELECT *
FROM NHACUNGCAP
WHERE THANHPHO = 'London';Lọc trực tiếp bằng WHERE THANHPHO = 'London'.
Dữ liệu mẫu có đúng 2 nhà cung cấp ở London (S1 Smith, S4 Clark) - So sánh chuỗi bằng dấu = là đủ, không cần LIKE vì tên thành phố khớp chính xác.
CÂU 4 · WHERE
Đề bài: Hiển thị mã phụ tùng, tên và màu sắc của tất cả các phụ tùng ở thành phố Paris.
SELECT MAPT, TENPT, MAUSAC
FROM PHUTUNG
WHERE THANHPHO = 'Paris';Cùng kỹ thuật với Câu 3, đổi bảng và điều kiện thành phố.
Kết quả gồm P2 (Bolt, Green) và P5 (Cam, Blue) - 2 phụ tùng duy nhất có THANHPHO = 'Paris' trong dữ liệu mẫu.
CÂU 5 · WHERE
Đề bài: Hiển thị mã phụ tùng, tên, khối lượng của những phụ tùng có khối lượng lớn hơn 15.
SELECT MAPT, TENPT, KHOILUONG
FROM PHUTUNG
WHERE KHOILUONG > 15;So sánh số bằng > trên cột KHOILUONG (kiểu FLOAT).
Kết quả gồm P2 (17), P3 (17), P6 (19) - "Lớn hơn 15" không bao gồm giá trị bằng 15 (ở đây không có phụ tùng nào đúng 15 nên không ảnh hưởng, nhưng vẫn cần phân biệt > với >= khi đọc đề).
CÂU 6 · WHERE ... AND
Đề bài: Tìm những phụ tùng (MAPT, TENPT, MAUSAC) có khối lượng lớn hơn 15, không phải màu đỏ (red).
SELECT MAPT, TENPT, MAUSAC
FROM PHUTUNG
WHERE KHOILUONG > 15 AND MAUSAC <> 'Red';Thêm điều kiện MAUSAC <> 'Red' nối bằng AND vào Câu 5.
Trong 3 phụ tùng thỏa Câu 5 (P2, P3, P6), P6 màu Red bị loại - Kết quả chỉ còn P2 (Green), P3 (Blue).
CÂU 7 · WHERE ... NOT IN
Đề bài: Tìm những phụ tùng (MAPT, TENPT, MAUSAC) có khối lượng lớn hơn 15, màu sắc khác màu đỏ (red) và xanh (green).
SELECT MAPT, TENPT, MAUSAC
FROM PHUTUNG
WHERE KHOILUONG > 15 AND MAUSAC NOT IN ('Red', 'Green');NOT IN ('Red', 'Green') loại cùng lúc 2 giá trị màu, gọn hơn viết MAUSAC <> 'Red' AND MAUSAC <> 'Green'.
Từ kết quả Câu 6 (P2 Green, P3 Blue), loại tiếp P2 vì màu Green - Chỉ còn P3 (Blue).
CÂU 8 · WHERE ... ORDER BY
Đề bài: Hiển thị những phụ tùng (MAPT, TENPT, khối lượng) có khối lượng lớn hơn 15 và nhỏ hơn 20, sắp xếp theo tên phụ tùng.
SELECT MAPT, TENPT, KHOILUONG
FROM PHUTUNG
WHERE KHOILUONG > 15 AND KHOILUONG < 20
ORDER BY TENPT;Khoảng giá trị mở ở cả 2 đầu (> 15 AND < 20, không bao gồm 15 và 20); ORDER BY TENPT sắp theo bảng chữ cái tên phụ tùng.
3 phụ tùng thỏa điều kiện là P2 (Bolt, 17), P3 (Screw, 17), P6 (Cog, 19) - Sắp theo tên cho ra thứ tự Bolt, Cog, Screw (không phải theo mã P2/P3/P6).
CÂU 9 · JOIN
Đề bài: Hiển thị những phụ tùng được vận chuyển bởi nhà cung cấp có mã số S1. Không hiển thị kết quả trùng (sử dụng phép kết).
SELECT DISTINCT pt.MAPT, pt.TENPT, pt.MAUSAC, pt.KHOILUONG, pt.THANHPHO
FROM PHUTUNG pt
JOIN VANCHUYEN vc ON pt.MAPT = vc.MAPT
WHERE vc.MANCC = 'S1';JOIN PHUTUNG với VANCHUYEN qua MAPT, lọc đúng nhà cung cấp S1; DISTINCT loại trùng.
1 phụ tùng có thể xuất hiện nhiều lần trong VANCHUYEN nếu được vận chuyển bởi nhiều nhà cung cấp khác nhau, nhưng ở đây lọc theo đúng 1 MANCC nên thực ra mỗi MAPT chỉ khớp 1 dòng (do khóa chính VANCHUYEN là cặp MANCC, MAPT) - DISTINCT vẫn nên giữ theo đúng yêu cầu đề, và là thói quen an toàn khi JOIN.
CÂU 10 · JOIN
Đề bài: Hiển thị những nhà cung cấp vận chuyển phụ tùng có mã là P1 (sử dụng phép kết).
SELECT DISTINCT ncc.MANCC, ncc.TENNCC, ncc.TRANGTHAI, ncc.THANHPHO
FROM NHACUNGCAP ncc
JOIN VANCHUYEN vc ON ncc.MANCC = vc.MANCC
WHERE vc.MAPT = 'P1';Cấu trúc đối xứng với Câu 9 - Đổi chiều JOIN từ NHACUNGCAP sang VANCHUYEN, lọc theo MAPT thay vì MANCC.
2 nhà cung cấp từng vận chuyển P1 là S1 và S2 - Đây là ví dụ về quan hệ N-N: 1 phụ tùng có thể do nhiều nhà cung cấp khác nhau vận chuyển.
CÂU 11 · JOIN 3 BẢNG
Đề bài: Hiển thị thông tin nhà cung cấp ở thành phố London và có vận chuyển phụ tùng của thành phố London. Không hiển thị kết quả trùng (sử dụng phép kết).
SELECT DISTINCT ncc.MANCC, ncc.TENNCC, ncc.TRANGTHAI, ncc.THANHPHO
FROM NHACUNGCAP ncc
JOIN VANCHUYEN vc ON ncc.MANCC = vc.MANCC
JOIN PHUTUNG pt ON vc.MAPT = pt.MAPT
WHERE ncc.THANHPHO = 'London' AND pt.THANHPHO = 'London';JOIN liên tiếp qua cả 3 bảng để vừa biết nhà cung cấp ở đâu, vừa biết phụ tùng họ vận chuyển ở đâu; 2 điều kiện THANHPHO = 'London' áp vào 2 bảng khác nhau (ncc và pt).
Dễ nhầm 2 điều kiện "London" thành cùng 1 ý, nhưng đây là 2 ràng buộc độc lập trên 2 thực thể khác nhau - Nhà cung cấp đặt tại London và (không nhất thiết cùng dòng dữ liệu) từng vận chuyển ít nhất 1 phụ tùng có xuất xứ London. Cả S1 và S4 đều thỏa (S1 vận chuyển P1/P4/P6 - Đều ở London; S4 vận chuyển P4 - Ở London).
CÂU 12 · SUBQUERY ... IN
Đề bài: Lặp lại câu 9 nhưng sử dụng toán tử IN.
SELECT MAPT, TENPT, MAUSAC, KHOILUONG, THANHPHO
FROM PHUTUNG
WHERE MAPT IN (
SELECT MAPT FROM VANCHUYEN WHERE MANCC = 'S1'
);Subquery độc lập lấy danh sách MAPT mà S1 từng vận chuyển; truy vấn ngoài lọc PHUTUNG theo danh sách đó bằng IN.
Cho cùng kết quả với Câu 9 nhưng không cần JOIN lẫn DISTINCT - Vì IN chỉ kiểm tra "có nằm trong danh sách" chứ không nhân dòng như JOIN, nên tự nhiên đã không trùng.
CÂU 13 · SUBQUERY ... IN
Đề bài: Lặp lại câu 10 nhưng sử dụng toán tử IN.
SELECT MANCC, TENNCC, TRANGTHAI, THANHPHO
FROM NHACUNGCAP
WHERE MANCC IN (
SELECT MANCC FROM VANCHUYEN WHERE MAPT = 'P1'
);Đối xứng với Câu 12, đổi chiều lọc từ MAPT sang MANCC.
Cùng lý do với Câu 12 - IN thay thế gọn cho cặp JOIN + DISTINCT khi chỉ cần lọc "có tồn tại quan hệ", không cần lấy thêm cột nào từ bảng trung gian VANCHUYEN.
CÂU 14 · SUBQUERY ... EXISTS
Đề bài: Lặp lại câu 9 nhưng sử dụng toán tử EXISTS.
SELECT MAPT, TENPT, MAUSAC, KHOILUONG, THANHPHO
FROM PHUTUNG pt
WHERE EXISTS (
SELECT * FROM VANCHUYEN vc
WHERE vc.MAPT = pt.MAPT AND vc.MANCC = 'S1'
);Subquery tương quan (correlated) - vc.MAPT = pt.MAPT tham chiếu ngược lại dòng PHUTUNG đang xét ở truy vấn ngoài, khác với subquery độc lập ở Câu 12.
3 cách viết (Câu 9 JOIN, Câu 12 IN, Câu 14 EXISTS) đều cho đúng cùng 1 kết quả - Khác nhau ở cách SQL Server tối ưu thực thi: EXISTS dừng ngay khi tìm được 1 dòng khớp đầu tiên, thường hiệu quả hơn IN khi bảng con lớn.
CÂU 15 · SUBQUERY ... EXISTS
Đề bài: Lặp lại câu 10 nhưng sử dụng toán tử EXISTS.
SELECT MANCC, TENNCC, TRANGTHAI, THANHPHO
FROM NHACUNGCAP ncc
WHERE EXISTS (
SELECT * FROM VANCHUYEN vc
WHERE vc.MANCC = ncc.MANCC AND vc.MAPT = 'P1'
);Đối xứng với Câu 14, tương quan qua MANCC thay vì MAPT.
3 câu 10/13/15 là bộ ba minh họa hoàn chỉnh cho cùng 1 câu hỏi bằng JOIN, IN, EXISTS - Nên tự làm cả 3 và so sánh kết quả để chắc chắn hiểu đúng cách vận hành từng kỹ thuật.
CÂU 16 · SUBQUERY ... IN
Đề bài: Lặp lại câu 11 nhưng sử dụng truy vấn con, dùng toán tử IN.
SELECT MANCC, TENNCC, TRANGTHAI, THANHPHO
FROM NHACUNGCAP
WHERE THANHPHO = 'London'
AND MANCC IN (
SELECT vc.MANCC
FROM VANCHUYEN vc
JOIN PHUTUNG pt ON vc.MAPT = pt.MAPT
WHERE pt.THANHPHO = 'London'
);Điều kiện "nhà cung cấp ở London" giữ nguyên ở truy vấn ngoài; điều kiện "từng vận chuyển phụ tùng London" chuyển thành 1 subquery độc lập trả về danh sách MANCC, so khớp bằng IN.
Subquery vẫn cần JOIN VANCHUYEN với PHUTUNG bên trong nó, vì phải biết phụ tùng nào ở London trước khi tra ngược ra nhà cung cấp - JOIN không biến mất hoàn toàn, chỉ chuyển vào trong subquery.
CÂU 17 · SUBQUERY ... EXISTS
Đề bài: Lặp lại câu 11 nhưng dùng truy vấn con, sử dụng toán tử EXISTS.
SELECT MANCC, TENNCC, TRANGTHAI, THANHPHO
FROM NHACUNGCAP ncc
WHERE THANHPHO = 'London'
AND EXISTS (
SELECT * FROM VANCHUYEN vc
JOIN PHUTUNG pt ON vc.MAPT = pt.MAPT
WHERE vc.MANCC = ncc.MANCC AND pt.THANHPHO = 'London'
);Giống Câu 16 nhưng subquery tương quan qua vc.MANCC = ncc.MANCC thay vì trả về danh sách rời rạc để so bằng IN.
Bộ ba Câu 11/16/17 hoàn chỉnh 3 cách viết (JOIN, IN, EXISTS) cho cùng 1 bài toán 2 điều kiện lồng nhau - Mức độ phức tạp cao hơn Câu 9-10 vì cần JOIN thêm 1 bảng ngay trong subquery.
CÂU 18 · NOT IN
Đề bài: Tìm nhà cung cấp chưa vận chuyển bất kỳ phụ tùng nào. Sử dụng NOT IN.
SELECT *
FROM NHACUNGCAP
WHERE MANCC NOT IN (
SELECT MANCC FROM VANCHUYEN
);NOT IN loại mọi nhà cung cấp có mã xuất hiện trong VANCHUYEN, chỉ giữ lại nhà cung cấp chưa từng vận chuyển gì.
Kết quả là S5 (Adams) - Nhà cung cấp duy nhất không có dòng nào trong VANCHUYEN. NOT IN an toàn ở đây vì VANCHUYEN.MANCC là 1 phần khóa chính, không bao giờ NULL.
CÂU 19 · NOT EXISTS
Đề bài: Tìm nhà cung cấp chưa vận chuyển bất kỳ phụ tùng nào. Sử dụng NOT EXISTS.
SELECT *
FROM NHACUNGCAP ncc
WHERE NOT EXISTS (
SELECT * FROM VANCHUYEN vc WHERE vc.MANCC = ncc.MANCC
);NOT EXISTS kiểm tra không tồn tại bất kỳ dòng VANCHUYEN nào khớp với nhà cung cấp đang xét.
Cho cùng kết quả S5 như Câu 18 - NOT EXISTS luôn là lựa chọn an toàn hơn NOT IN về lâu dài (không sợ bẫy NULL), dù ở bài này cả 2 đều đúng vì không có NULL trong VANCHUYEN.MANCC.
CÂU 20 · OUTER JOIN
Đề bài: Tìm nhà cung cấp chưa vận chuyển bất kỳ phụ tùng nào. Sử dụng outer JOIN (phép kết ngoài).
SELECT ncc.*
FROM NHACUNGCAP ncc
LEFT JOIN VANCHUYEN vc ON ncc.MANCC = vc.MANCC
WHERE vc.MANCC IS NULL;LEFT JOIN giữ lại mọi nhà cung cấp kể cả không khớp được dòng VANCHUYEN nào (cột phía vc sẽ là NULL); lọc WHERE vc.MANCC IS NULL chính là kỹ thuật "anti-join" kinh điển.
Bộ ba Câu 18/19/20 là 3 cách kinh điển nhất để trả lời câu hỏi "không có bất kỳ" trong SQL - NOT IN, NOT EXISTS, và LEFT JOIN ... IS NULL - Nên thuộc lòng cả 3 vì đây là dạng câu hỏi cực kỳ phổ biến trong đề thi thực hành.
CÂU 21 · COUNT
Đề bài: Có tất cả bao nhiêu nhà cung cấp?
SELECT COUNT(*) AS SoLuongNCC
FROM NHACUNGCAP;COUNT(*) đếm toàn bộ số dòng trong bảng.
Dữ liệu mẫu có đúng 5 nhà cung cấp (S1-S5).
CÂU 22 · COUNT ... WHERE
Đề bài: Có tất cả bao nhiêu nhà cung cấp ở London?
SELECT COUNT(*) AS SoLuongNCC_London
FROM NHACUNGCAP
WHERE THANHPHO = 'London';WHERE lọc trước, COUNT(*) đếm sau - Chỉ đếm những dòng đã qua bộ lọc.
Kết quả là 2 (S1, S4) - Khác Câu 21 ở chỗ có thêm WHERE để giới hạn phạm vi đếm.
CÂU 23 · MAX / MIN
Đề bài: Hiển thị trị giá cao nhất, thấp nhất của TRANGTHAI của các nhà cung cấp.
SELECT MAX(TRANGTHAI) AS TrangThaiCaoNhat, MIN(TRANGTHAI) AS TrangThaiThapNhat
FROM NHACUNGCAP;MAX() và MIN() có thể tính cùng lúc trong 1 câu SELECT, không cần 2 câu riêng.
TRANGTHAI của 5 nhà cung cấp là 20, 10, 30, 20, 30 - Cao nhất 30, thấp nhất 10.
CÂU 24 · MAX / MIN ... WHERE
Đề bài: Hiển thị giá trị cao nhất, thấp nhất của TRANGTHAI trong bảng NHACUNGCAP ở thành phố London.
SELECT MAX(TRANGTHAI) AS TrangThaiCaoNhat, MIN(TRANGTHAI) AS TrangThaiThapNhat
FROM NHACUNGCAP
WHERE THANHPHO = 'London';Thêm WHERE THANHPHO = 'London' trước khi tính MAX/MIN, khác Câu 23 tính trên toàn bảng.
2 nhà cung cấp ở London (S1, S4) đều có TRANGTHAI = 20, nên cả cao nhất lẫn thấp nhất đều ra 20 - Không phải lỗi, chỉ là trùng hợp dữ liệu.
CÂU 25 · GROUP BY ... SUM
Đề bài: Mỗi nhà cung cấp vận chuyển bao nhiêu phụ tùng? Chỉ hiển thị mã nhà cung cấp, tổng số phụ tùng đã vận chuyển.
SELECT MANCC, SUM(SOLUONG) AS TongSoLuong
FROM VANCHUYEN
GROUP BY MANCC;GROUP BY MANCC tách dữ liệu theo từng nhà cung cấp; SUM(SOLUONG) cộng dồn số lượng trong mỗi nhóm.
"Bao nhiêu phụ tùng" ở đây hiểu là tổng số lượng đã vận chuyển (cột SOLUONG), không phải đếm số loại phụ tùng khác nhau - Kết quả: S1=1300, S2=700, S3=200, S4=900. S5 không xuất hiện vì GROUP BY chạy trên VANCHUYEN, nơi S5 không có dòng nào.
CÂU 26 · JOIN ... GROUP BY ... SUM
Đề bài: Mỗi nhà cung cấp vận chuyển bao nhiêu phụ tùng? Hiển thị mã nhà cung cấp, tên, thành phố của nhà cung cấp và tổng số phụ tùng đã vận chuyển.
SELECT ncc.MANCC, ncc.TENNCC, ncc.THANHPHO, SUM(vc.SOLUONG) AS TongSoLuong
FROM NHACUNGCAP ncc
JOIN VANCHUYEN vc ON ncc.MANCC = vc.MANCC
GROUP BY ncc.MANCC, ncc.TENNCC, ncc.THANHPHO;Cùng ý tưởng Câu 25 nhưng phải JOIN thêm NHACUNGCAP để lấy TENNCC/THANHPHO, nên GROUP BY phải liệt kê đủ 3 cột không tổng hợp.
SQL Server bắt buộc mọi cột xuất hiện trong SELECT mà không nằm trong hàm tổng hợp đều phải có mặt trong GROUP BY - Thiếu TENNCC hoặc THANHPHO trong GROUP BY sẽ báo lỗi cú pháp.
CÂU 27 · GROUP BY ... HAVING
Đề bài: Nhà cung cấp nào đã vận chuyển tổng cộng nhiều hơn 500 phụ tùng? Chỉ hiển thị mã nhà cung cấp.
SELECT MANCC
FROM VANCHUYEN
GROUP BY MANCC
HAVING SUM(SOLUONG) > 500;HAVING SUM(SOLUONG) > 500 lọc theo kết quả tổng hợp sau khi đã GROUP BY, khác WHERE chỉ lọc được từng dòng gốc.
Không thể viết WHERE SUM(SOLUONG) > 500 vì tại thời điểm WHERE chạy, dữ liệu chưa được gom nhóm nên SUM() chưa có giá trị - Từ kết quả Câu 25 (S1=1300, S2=700, S3=200, S4=900), chỉ S3 (200) bị loại.
CÂU 28 · JOIN ... GROUP BY ... HAVING
Đề bài: Nhà cung cấp nào đã vận chuyển nhiều hơn 300 phụ tùng màu đỏ (red)? Chỉ hiển thị mã nhà cung cấp.
SELECT vc.MANCC
FROM VANCHUYEN vc
JOIN PHUTUNG pt ON vc.MAPT = pt.MAPT
WHERE pt.MAUSAC = 'Red'
GROUP BY vc.MANCC
HAVING SUM(vc.SOLUONG) > 300;WHERE pt.MAUSAC = 'Red' lọc trước khi gom nhóm (chỉ giữ dòng vận chuyển phụ tùng đỏ), rồi mới GROUP BY + HAVING để lọc theo tổng số lượng.
Phụ tùng đỏ gồm P1, P4, P6. Riêng từng nhà cung cấp: S1 vận chuyển đỏ P1(300)+P4(200)+P6(100)=600; S2 vận chuyển đỏ P1(300)=300; S4 vận chuyển đỏ P4(300)=300 - Chỉ S1 có tổng lớn hơn 300 (S2, S4 đúng bằng 300 nên không thỏa "nhiều hơn").
CÂU 29 · JOIN ... GROUP BY ... HAVING
Đề bài: Nhà cung cấp nào đã vận chuyển nhiều hơn 300 phụ tùng màu đỏ (red)? Hiển thị mã nhà cung cấp, tên, thành phố và số lượng phụ tùng màu đỏ đã vận chuyển.
SELECT ncc.MANCC, ncc.TENNCC, ncc.THANHPHO, SUM(vc.SOLUONG) AS SoLuongDo
FROM NHACUNGCAP ncc
JOIN VANCHUYEN vc ON ncc.MANCC = vc.MANCC
JOIN PHUTUNG pt ON vc.MAPT = pt.MAPT
WHERE pt.MAUSAC = 'Red'
GROUP BY ncc.MANCC, ncc.TENNCC, ncc.THANHPHO
HAVING SUM(vc.SOLUONG) > 300;Cùng logic Câu 28, thêm JOIN NHACUNGCAP để lấy TENNCC/THANHPHO, giống cách Câu 26 mở rộng từ Câu 25.
Kết quả chỉ còn đúng 1 dòng: S1, Smith, London, 600 - Khớp với phân tích ở Câu 28.
CÂU 30 · GROUP BY
Đề bài: Có bao nhiêu nhà cung cấp ở mỗi thành phố.
SELECT THANHPHO, COUNT(*) AS SoLuongNCC
FROM NHACUNGCAP
GROUP BY THANHPHO;GROUP BY THANHPHO tách nhà cung cấp theo từng thành phố; COUNT(*) đếm số lượng trong mỗi nhóm.
Kết quả: London=2 (S1, S4), Paris=2 (S2, S3), Athens=1 (S5) - Đủ cả 5 nhà cung cấp, khác với Câu 25 (nơi S5 bị thiếu vì bảng nguồn là VANCHUYEN chứ không phải NHACUNGCAP).
CÂU 31 · JOIN + GROUP BY + ORDER BY + TOP
Đề bài: Nhà cung cấp nào đã vận chuyển nhiều phụ tùng nhất? Hiển thị tên nhà cung cấp và số lượng phụ tùng đã vận chuyển.
SELECT TOP 1 WITH TIES ncc.TENNCC, SUM(vc.SOLUONG) AS TongSoLuong
FROM NHACUNGCAP ncc
JOIN VANCHUYEN vc ON ncc.MANCC = vc.MANCC
GROUP BY ncc.TENNCC
ORDER BY TongSoLuong DESC;Kết hợp JOIN (lấy tên nhà cung cấp), GROUP BY (cộng dồn số lượng theo từng nhà cung cấp) và ORDER BY ... DESC + TOP 1 WITH TIES (lấy nhà cung cấp nhiều nhất, giữ luôn các nhà cung cấp đồng hạng nếu có).
Đây là ví dụ điển hình của việc ghép nhiều kỹ thuật đã học trong 1 câu - Từ bảng tổng số lượng ở Câu 25 (S1=1300, S2=700, S3=200, S4=900), S1 (Smith) dẫn đầu với 1300, không có nhà cung cấp nào khác đồng hạng nên kết quả chỉ có đúng 1 dòng.
CÂU 32 · INTERSECT
Đề bài: Thành phố nào có cả nhà cung cấp và phụ tùng.
SELECT THANHPHO FROM NHACUNGCAP
INTERSECT
SELECT THANHPHO FROM PHUTUNG;Cách khác (subquery IN)
SELECT DISTINCT THANHPHO
FROM NHACUNGCAP
WHERE THANHPHO IN (SELECT THANHPHO FROM PHUTUNG);INTERSECT tự động loại trùng nên không cần DISTINCT; cách IN phải tự thêm DISTINCT vì NHACUNGCAP có thể có nhiều nhà cung cấp cùng 1 thành phố.
INTERSECT lấy giao giữa 2 tập THANHPHO - Chỉ giữ lại thành phố xuất hiện ở cả 2 bảng.
Thành phố của nhà cung cấp: London, Paris, Athens. Thành phố của phụ tùng: London, Paris, Oslo - Giao nhau chỉ còn London và Paris (Athens chỉ có nhà cung cấp, Oslo chỉ có phụ tùng).
CÂU 33 · INSERT
Đề bài: Viết câu lệnh SQL để insert nhà cung cấp mới: S6, Duncan, 30, Paris.
INSERT INTO NHACUNGCAP (MANCC, TENNCC, TRANGTHAI, THANHPHO)
VALUES ('S6', 'Duncan', 30, 'Paris');INSERT INTO ... (danh sách cột) VALUES (...) thêm đúng 1 dòng mới với giá trị theo đúng thứ tự đã liệt kê.
Nên liệt kê rõ tên cột thay vì chỉ VALUES (...) - Giúp câu lệnh không phụ thuộc vào đúng thứ tự cột vật lý của bảng, dễ đọc và ít lỗi hơn khi bảng có nhiều cột.
CÂU 34 · UPDATE
Đề bài: Viết câu lệnh SQL để thay đổi thành phố của S6 (ở câu 33) thành Sydney.
UPDATE NHACUNGCAP
SET THANHPHO = 'Sydney'
WHERE MANCC = 'S6';UPDATE ... SET ... WHERE chỉ sửa đúng dòng có MANCC = 'S6' vừa thêm ở Câu 33.
WHERE trong câu UPDATE bắt buộc phải lọc đúng MANCC - Nếu quên WHERE, toàn bộ nhà cung cấp trong bảng sẽ bị đổi thành "Sydney".
CÂU 35 · UPDATE
Đề bài: Viết câu lệnh SQL tăng TRANGTHAI của nhà cung cấp ở London lên thêm 10.
UPDATE NHACUNGCAP
SET TRANGTHAI = TRANGTHAI + 10
WHERE THANHPHO = 'London';SET TRANGTHAI = TRANGTHAI + 10 lấy giá trị hiện tại của chính cột đó rồi cộng thêm 10, áp dụng cho mọi dòng khớp WHERE.
Khác Câu 34 (sửa 1 dòng theo khóa chính), câu này cố ý sửa nhiều dòng cùng lúc (S1 và S4 đều ở London) - WHERE THANHPHO = 'London' vẫn là bắt buộc, chỉ là điều kiện lọc theo thuộc tính khác thay vì khóa chính.
CÂU 36 · DELETE
Đề bài: Viết câu lệnh SQL xóa nhà cung cấp S6.
DELETE FROM NHACUNGCAP
WHERE MANCC = 'S6';DELETE FROM ... WHERE xóa đúng dòng có MANCC = 'S6'.
S6 không xuất hiện trong VANCHUYEN (chưa từng vận chuyển gì) nên xóa được ngay - Nếu S6 đã có dòng liên kết trong VANCHUYEN, ràng buộc khóa ngoại FKShip1 sẽ chặn lệnh DELETE này lại cho đến khi xóa hết các dòng VANCHUYEN liên quan trước.
