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

  • JOIN là công cụ mạnh để liên kết dữ liệu từ nhiều bảng.

  • Subquery giú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

  1. 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ọ.
  2. 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.
  3. 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ó).
  4. 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.
  5. Sử dụng Subquery trong SELECT

    • 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.
  6. Sử dụng Subquery trong WHERE

    • 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.
  7. Sử dụng Subquery trong FROM

    • 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