Bài 1: Giới thiệu về Trình quản lý quảng cáo
Bài giảng: Truy vấn nhiều bảng, truy vấn con
1. Giới thiệu
Trong SQL, chúng ta thường làm việc với dữ liệu từ nhiều bảng. Việc kết hợp dữ liệu từ nhiều bảng giúp truy xuất thông tin một cách chính xác và hiệu quả.
SQL cung cấp các phương pháp:
- JOIN (INNER, LEFT, RIGHT, FULL) để kết hợp dữ liệu từ nhiều bảng.
- Subquery (truy vấn con) để lồng các truy vấn bên trong nhau.
2. Các bảng dữ liệu đơn giản
Chuẩn bị các bảng dữ liệu sau:
Bảng 1. Khóa học:
| KhoaHoc | |
| #ID | int |
| TenKhoaHoc | nvarchar(200) |
| idChuDe | int |
| ThuTu | int |
| HinhAnh | nvarchar(500) |
| MoTa | nvarchar(500) |
| BaiViet | nvarchar(Max) |
| GiangVien | nvarchar(500) |
| ThoiGianTao | date |
| isCongKhai | bit |
CREATE TABLE KhoaHoc (
ID INT PRIMARY KEY,
TenKhoaHoc NVARCHAR(200) NOT NULL,
idChuDe INT,
ThuTu INT,
HinhAnh NVARCHAR(500),
MoTa NVARCHAR(500),
BaiViet NVARCHAR(MAX),
GiangVien NVARCHAR(500),
ThoiGianTao DATE,
isCongKhai BIT
);
INSERT INTO KhoaHoc (
ID, TenKhoaHoc, idChuDe, ThuTu, HinhAnh, MoTa, BaiViet,
GiangVien, ThoiGianTao, isCongKhai
)
VALUES
(1, N'Lập trình Python cơ bản', 1, 1,
N'https://example.com/img/python.jpg',
N'Khóa học dành cho người mới học Python, từ cơ bản đến nâng cao.',
N'<p>Chào mừng bạn đến với khóa học Python. Hãy bắt đầu với cài đặt và cú pháp cơ bản.</p>',
N'Nguyễn Văn A', '2025-06-01', 1),
(2, N'Thiết kế Web với HTML/CSS', 2, 2,
N'https://example.com/img/html_css.jpg',
N'Hướng dẫn xây dựng trang web từ giao diện đến layout bằng HTML và CSS.',
N'<p>Khóa học tập trung vào kỹ thuật thiết kế và xây dựng trang web chuẩn W3C.</p>',
N'Lê Thị B', '2025-06-10', 1),
(3, N'Cơ sở dữ liệu SQL Server', 3, 3,
N'https://example.com/img/sql.jpg',
N'Tìm hiểu cách tạo, truy vấn và quản lý dữ liệu trong SQL Server.',
N'<p>Bạn sẽ học cách sử dụng các lệnh SQL để làm việc hiệu quả với CSDL.</p>',
N'Trần Văn C', '2025-06-15', 0);
Bảng 2. Video
| Video | |
| #ID | int |
| idKhoaHoc | int |
| TieuDe | nvarchar(500) |
| MoTa | nvarchar(500) |
| UrlVideo | nvarchar(500) |
| HinhAnh | nvarchar(500) |
| ThuTu | int |
| ThoiGianTao | DateTime |
| LuotXem | int |
| LuotThich | int |
CREATE TABLE Video (
ID INT PRIMARY KEY,
idKhoaHoc INT,
TieuDe NVARCHAR(500),
MoTa NVARCHAR(500),
UrlVideo NVARCHAR(500),
HinhAnh NVARCHAR(500),
ThuTu INT,
ThoiGianTao DATETIME,
LuotXem INT,
LuotThich INT,
FOREIGN KEY (idKhoaHoc) REFERENCES KhoaHoc(ID)
);
INSERT INTO Video (
[ID], [idKhoaHoc], [TieuDe], [MoTa], [UrlVideo], [HinhAnh],
[ThuTu], [ThoiGianTao], [LuotXem], [LuotThich]
)
VALUES
(1, 1, N'Giới thiệu Python', N'Giới thiệu tổng quan về Python và các ứng dụng.',
N'https://example.com/videos/python_intro.mp4',
N'https://example.com/images/python_intro.jpg',
1, '2025-06-01 10:00:00', 150, 45),
(2, 2, N'Cấu trúc HTML cơ bản', N'Học về các thẻ HTML và cách xây dựng trang web.',
N'https://example.com/videos/html_structure.mp4',
N'https://example.com/images/html_structure.jpg',
1, '2025-06-11 09:30:00', 200, 60),
(3, 3, N'Tạo bảng SQL Server', N'Hướng dẫn tạo bảng và định nghĩa dữ liệu trong SQL Server.',
N'https://example.com/videos/sql_create_table.mp4',
N'https://example.com/images/sql_create_table.jpg',
1, '2025-06-16 14:00:00', 120, 35);
Bảng 3: Chủ đề
| ChuDe | |
| #ID | int |
| TenChuDe | nvarchar(500) |
| ThuTu | int |
| HinhAnh | nvarchar(500) |
CREATE TABLE ChuDe (
ID INT PRIMARY KEY,
TenChuDe NVARCHAR(500),
ThuTu NVARCHAR(500),
HinhAnh NVARCHAR(500)
);
INSERT INTO ChuDe (
[ID], [TenChuDe], [ThuTu], [HinhAnh]
)
VALUES
(1, N'Lập trình', N'1', N'https://example.com/img/lap-trinh.png'),
(2, N'Thiết kế Web', N'2', N'https://example.com/img/thiet-ke-web.png'),
(3, N'Cơ sở dữ liệu', N'3', N'https://example.com/img/co-so-du-lieu.png');
3. Kết hợp bảng bằng JOIN trong hệ thống khóa học
Trong hệ quản trị CSDL, JOIN được dùng để kết hợp dữ liệu từ nhiều bảng dựa trên mối quan hệ giữa chúng.
Trong ví dụ này, chúng ta sử dụng các bảng:
-
KhoaHoc: Thông tin khóa học. -
Video: Danh sách video thuộc từng khóa học. -
ChuDe: Chủ đề mà mỗi khóa học thuộc về.
3.1 INNER JOIN – Chỉ lấy dữ liệu khớp ở cả 2 bảng
Mục tiêu: Lấy danh sách video và thông tin khóa học tương ứng.
SELECT
Video.TieuDe,
KhoaHoc.TenKhoaHoc,
KhoaHoc.GiangVien
FROM Video
INNER JOIN KhoaHoc ON Video.idKhoaHoc = KhoaHoc.ID;
Giải thích:
Lệnh này chỉ lấy các dòng có idKhoaHoc khớp với ID trong bảng KhoaHoc.
3.2 LEFT JOIN – Lấy tất cả bên trái, có hay không có bên phải
Mục tiêu: Lấy tất cả khóa học, kể cả những khóa học chưa có video nào.
SELECT
KhoaHoc.TenKhoaHoc,
Video.TieuDe,
Video.UrlVideo
FROM KhoaHoc
LEFT JOIN Video ON KhoaHoc.ID = Video.idKhoaHoc;
Giải thích:
Khóa học không có video sẽ vẫn hiển thị, phần video là NULL.
3.3 RIGHT JOIN – Lấy tất cả bên phải, kể cả khi bên trái không có
Mục tiêu: Lấy tất cả video, kể cả những video không khớp khóa học nào (lỗi dữ liệu).
SELECT
Video.TieuDe,
KhoaHoc.TenKhoaHoc,
KhoaHoc.GiangVien
FROM KhoaHoc
RIGHT JOIN Video ON KhoaHoc.ID = Video.idKhoaHoc;
Giải thích:
Nếu có video nào không gắn với khóa học (sai idKhoaHoc), nó vẫn được hiển thị.
3.4 FULL JOIN – Lấy tất cả cả 2 bảng, có hay không có mối quan hệ
Mục tiêu: Lấy tất cả khóa học và tất cả video, dù có gắn với nhau hay không.
SELECT
KhoaHoc.TenKhoaHoc,
Video.TieuDe,
Video.UrlVideo
FROM KhoaHoc
FULL JOIN Video ON KhoaHoc.ID = Video.idKhoaHoc;
4. Truy vấn con (Subquery)
4.1 Trong SELECT – Tính tổng lượt xem theo từng khóa học
SELECT
TenKhoaHoc,
(SELECT SUM(LuotXem)
FROM Video
WHERE Video.idKhoaHoc = KhoaHoc.ID) AS TongLuotXem
FROM KhoaHoc;
4.2 Trong WHERE – Lọc video có lượt xem lớn hơn trung bình
SELECT * FROM Video
WHERE LuotXem > (SELECT AVG(LuotXem) FROM Video);
5. Kết luận
-
JOINlà công cụ mạnh để liên kết dữ liệu từ nhiều bảng. -
Subquerygiúp xử lý dữ liệu nâng cao hơn. -
Kết hợp cả hai giúp viết các truy vấn SQL linh hoạt, mạnh mẽ, và tối ưu hiệu suất trong hệ thống học trực tuyến.
1. Lệnh Tạo Bảng và Thêm Dữ Liệu
1.1. Tạo bảng NhanVien (Danh sách nhân viên)
CREATE TABLE NhanVien (
ID INT PRIMARY KEY,
TenNV VARCHAR(50),
PhongBan VARCHAR(50),
Luong INT
);
Chèn dữ liệu vào bảng NhanVien
INSERT INTO NhanVien (ID, TenNV, PhongBan, Luong) VALUES
(1, 'An', 'IT', 1500),
(2, 'Binh', 'Kinh doanh', 1800),
(3, 'Chi', 'IT', 1600),
(4, 'Dung', 'Nhân sự', 1400),
(5, 'Hoa', 'Kinh doanh', 2000);
| ID | TenNV | PhongBan | Luong |
|---|---|---|---|
| 1 | An | IT | 1500 |
| 2 | Binh | Kinh doanh | 1800 |
| 3 | Chi | IT | 1600 |
| 4 | Dung | Nhân sự | 1400 |
| 5 | Hoa | Kinh doanh | 2000 |
1.2. Tạo bảng DuAn (Danh sách dự án và nhân viên tham gia)
CREATE TABLE DuAn (
ID INT PRIMARY KEY,
TenDuAn VARCHAR(50),
ID_NhanVien INT,
SoGioLam INT,
FOREIGN KEY (ID_NhanVien) REFERENCES NhanVien(ID)
);
Chèn dữ liệu vào bảng DuAn
INSERT INTO DuAn (ID, TenDuAn, ID_NhanVien, SoGioLam) VALUES
(1, 'Website A', 1, 20),
(2, 'Website B', 3, 25),
(3, 'Marketing X', 2, 30),
(4, 'Website A', 3, 15),
(5, 'HR System', 4, 10),
(6, 'Marketing X', 5, 35);
| ID | TenDuAn | ID_NhanVien | SoGioLam |
|---|---|---|---|
| 1 | Website A | 1 | 20 |
| 2 | Website B | 3 | 25 |
| 3 | Marketing X | 2 | 30 |
| 4 | Website A | 3 | 15 |
| 5 | HR System | 4 | 10 |
| 6 | Marketing X | 5 | 35 |
Câu hỏi bài tập
-
Sử dụng
INNER JOIN- Liệt kê danh sách nhân viên tham gia vào các dự án cùng số giờ làm việc của họ.
-
Sử dụng
LEFT JOIN- Liệt kê danh sách tất cả nhân viên, bao gồm cả những người chưa tham gia dự án nào.
-
Sử dụng
RIGHT JOIN- Liệt kê danh sách tất cả các dự án, kể cả những dự án chưa có nhân viên tham gia (nếu có).
-
Sử dụng
FULL JOIN- Lấy danh sách đầy đủ các nhân viên và các dự án, bao gồm cả nhân viên chưa có dự án và dự án chưa có nhân viên.
-
Sử dụng
SubquerytrongSELECT- Hiển thị danh sách nhân viên và tổng số giờ họ đã làm ở tất cả các dự án.
-
Sử dụng
SubquerytrongWHERE- Liệt kê các nhân viên có mức lương cao hơn mức lương trung bình của tất cả nhân viên.
-
Sử dụng
SubquerytrongFROM- Tạo bảng tạm tính tổng số giờ làm việc của từng phòng ban và hiển thị danh sách phòng ban cùng tổng giờ làm việc.
Yêu cầu nộp bài: File SQL hoặc word