SQL Pattern Guide

Phân Loại Dạng SQL

QuanLyDiemTruongDaiHoc — 45 câu truy vấn được phân loại theo dạng, khung giải và cách nhận biết

🔗
JOIN Cơ Bản
Kết hợp nhiều bảng để lấy thông tin liên quan
Câu 1, 2, 8, 10, 25
Câu 1Câu 10
INNER JOIN nhiều bảng + điều kiện lọc cụ thể
Lấy thông tin từ nhiều bảng theo điều kiện WHERE xác định (mã HP, mã LHP...)
  • Đề yêu cầu "danh sách ... của ... mã ... '...' ".
  • Cần lấy cột từ ít nhất 2–3 bảng khác nhau (SV, LHP, điểm...).
  • Có điều kiện lọc cố định: MaHP = '...' AND MaLHP = '...'.
  • Không yêu cầu GROUP BY hay tổng hợp.
SELECT sv.MaSV, sv.HoTen, sv.MaLop, sv.NgaySinh,
       lhpsv.DiemQT, lhpsv.DiemThi, lhpsv.DiemTKHP
FROM   SinhVien sv
INNER JOIN LopHocPhan_SinhVien lhpsv
       ON sv.MaSV = lhpsv.MaSV
INNER JOIN LopHocPhan lhp
       ON lhpsv.MaHP = lhp.MaHP
      AND lhpsv.MaLHP = lhp.MaLHP
WHERE lhp.MaHP  = 'MaHocPhan'
  AND lhp.MaLHP = 'MaLopHocPhan';

💡 Thêm bảng nào cần thêm INNER JOIN tương ứng. Điều kiện WHERE cố định.

Câu 1 Danh sách SV điểm lớp HP 'IT1.110.3', LHP '1-2-22-QT08'.
Câu 10 Thông tin chi tiết LHP mà SV '212606016' đang học kèm điểm.
Câu 2Câu 25
SELF JOIN / LEFT JOIN để lấy thông tin liên quan (quản lý, tiên quyết)
Kết nối bảng với chính nó hoặc bảng phụ để lấy thông tin cha–con
  • Đề có cụm "trưởng/chủ nhiệm", "quản lý", "tiên quyết", "cha – con".
  • Một bảng có FK tự trỏ về chính nó hoặc có bảng phụ lưu quan hệ tiên quyết.
  • Yêu cầu "nếu có" → dùng LEFT JOIN để giữ bản ghi không có liên kết.
-- Ví dụ: Bộ môn + Trưởng bộ môn
SELECT bm.MaBM, bm.TenBM, gv.MaGV, gv.HoTen
FROM   BoMon bm
INNER JOIN GiangVien gv
       ON bm.MaTBM = gv.MaGV;  -- FK trưởng bộ môn

-- Ví dụ: Học phần + tiên quyết (nếu có)
SELECT hp.MaHP, hp.TenHP,
       tq.MaHP AS MaHPTQ, hp2.TenHP AS TenHPTQ
FROM   HocPhan hp
LEFT JOIN TienQuyet tq  ON hp.MaHP = tq.MaHP
LEFT JOIN HocPhan  hp2 ON tq.MaHPTQ = hp2.MaHP;
Câu 2 GV là trưởng bộ môn cùng thông tin bộ môn họ quản lý.
Câu 25 Học phần và học phần tiên quyết (tên + mã), nếu có.
Câu 8
JOIN + GROUP BY đếm số lượng theo nhóm
Kết bảng rồi GROUP BY để COUNT số học phần / SV / LHP theo đơn vị
  • Đề yêu cầu "số học phần mà mỗi bộ môn..." / "số sinh viên mỗi lớp...".
  • Cần đếm (COUNT) theo nhóm → bắt buộc có GROUP BY.
  • Có điều kiện thuộc khoa/đơn vị cụ thể → thêm WHERE trước GROUP BY.
SELECT bm.MaBM, bm.TenBM, COUNT(hp.MaHP) AS SoHocPhan
FROM   BoMon bm
INNER JOIN HocPhan hp ON bm.MaBM = hp.MaBM
INNER JOIN Khoa    k  ON bm.MaKhoa = k.MaKhoa
WHERE  k.TenKhoa LIKE N'%Công nghệ thông tin%'
GROUP BY bm.MaBM, bm.TenBM;
Câu 8 Số học phần mỗi bộ môn của Khoa CNTT phụ trách.
📊
Tổng Hợp / GROUP BY
COUNT, AVG, SUM, HAVING theo nhóm
Câu 9, 13, 14, 19, 26, 27, 28, 29, 30, 44
Câu 9Câu 13Câu 29Câu 30
COUNT + GROUP BY + HAVING (lọc nhóm thỏa điều kiện)
Đếm số lượng theo nhóm và chỉ lấy nhóm thỏa ngưỡng
  • Đề yêu cầu "số lớp/sinh viên/học phần" theo từng đơn vị.
  • Có điều kiện "lớn hơn X", "từ Y trở lên" trên kết quả nhóm → HAVING.
  • Sắp xếp "giảm dần" / "tăng dần" → thêm ORDER BY ... DESC/ASC.
SELECT NhomCot, COUNT(*) AS SoLuong
FROM   Bang
JOIN   BangLien ON ...dk_join...
WHERE  ...dieu_kien_loc...          -- lọc trước nhóm
GROUP BY NhomCot
HAVING COUNT(*) > nguong          -- lọc SAU nhóm
ORDER BY SoLuong DESC;

⚡ Nhớ: WHERE lọc hàng, HAVING lọc nhóm — không được hoán đổi.

Câu 9 GV + số LHP đảm nhiệm HK2 2023-2024.
Câu 13 Số SV đăng ký mỗi học phần HK2 2023-2024, sắp xếp giảm dần.
Câu 29 Tổng SV đăng ký LHP theo từng năm học và học kỳ.
Câu 30 Khoa có số SV > 2000.
Câu 14Câu 26
AVG + GROUP BY — Trung bình điểm theo nhóm
Tính điểm trung bình của các nhóm (lớp, khoa, CTDT...)
  • Đề dùng từ "trung bình", "điểm tích lũy trung bình", "tính trung bình theo...".
  • Nhóm hóa theo lớp / khoa / chương trình → GROUP BY.
SELECT NhomCot, AVG(DiemTKHP) AS DiemTBNhom
FROM   LopHocPhan_SinhVien lhpsv
JOIN   BangNhom bn ON ...join...
WHERE  lhpsv.DiemTKHP IS NOT NULL
GROUP BY NhomCot;
Câu 14 Điểm tích lũy TB của SV Khoa CNTT theo từng CTDT.
Câu 26 Trung bình DiemTKHP theo từng LHP.
Câu 19Câu 44
Tỷ lệ % theo nhóm (CASE WHEN + AVG/COUNT)
Tính % sinh viên đạt/không đạt, phân phối điểm theo lớp
  • Đề có cụm "số phần trăm", "tỷ lệ", "bao nhiêu % đạt".
  • Cần chia theo nhiều khoảng điểm hoặc điều kiện → CASE WHEN bên trong hàm tổng hợp.
  • Dùng * 100.0 / COUNT(*) để tính phần trăm.
SELECT
  MaLHP,
  COUNT(*) AS TongSV,
  ROUND(
    SUM(CASE WHEN DiemTKHP >= 8.5 THEN 1 ELSE 0 END)
    * 100.0 / COUNT(*), 2)        AS PhanTramTren85,
  ROUND(
    SUM(CASE WHEN DiemTKHP >= 7
              AND  DiemTKHP < 8.5 THEN 1 ELSE 0 END)
    * 100.0 / COUNT(*), 2)        AS PhanTram7to85
  -- ... thêm các dải điểm còn lại ...
FROM   LopHocPhan_SinhVien
GROUP BY MaLHP
HAVING SUM(CASE WHEN DiemTKHP >= 4 THEN 1 ELSE 0 END)
       * 100.0 / COUNT(*) < 50;  -- câu 44: chỉ lớp < 50%
Câu 19 % SV theo dải điểm (>8.5, 7–8.5, 5.5–7, 4–5.5, <4) từng LHP CNTT HK2 2023-2024.
Câu 44 Tỷ lệ % SV đạt (≥4) mỗi LHP — chỉ hiện LHP tỷ lệ đạt < 50%.
🔍
Subquery / EXISTS / NOT EXISTS
Tìm bản ghi "chưa có", "chưa học", "không tồn tại"
Câu 3, 6, 12, 15, 21, 24, 34, 45
Câu 3Câu 21Câu 24
NOT EXISTS / LEFT JOIN IS NULL — "Chưa được phân công" / "Chưa có SV"
Tìm bản ghi không có bản ghi tương ứng ở bảng khác
  • Từ khóa: "chưa được phân công", "không có SV đăng ký", "chưa có SV".
  • Logic: bảng A không xuất hiện trong bảng B theo một điều kiện.
  • Có thể dùng NOT EXISTS hoặc LEFT JOIN ... WHERE ... IS NULL.
-- Cách 1: NOT EXISTS
SELECT gv.*
FROM   GiangVien gv
WHERE NOT EXISTS (
  SELECT 1 FROM LopHocPhan lhp
  WHERE  lhp.MaGV     = gv.MaGV
    AND  lhp.NamHoc   = '2023-2024'
    AND  lhp.HocKy    = 2
);

-- Cách 2: LEFT JOIN + IS NULL (tương đương)
SELECT gv.*
FROM   GiangVien gv
LEFT JOIN LopHocPhan lhp
       ON  lhp.MaGV   = gv.MaGV
      AND  lhp.NamHoc = '2023-2024'
      AND  lhp.HocKy  = 2
WHERE lhp.MaGV IS NULL;
Câu 3 GV chưa được phân công LHP HK2 2023-2024.
Câu 21 GV không có SV đăng ký trong LHP của họ.
Câu 24 Học phần chưa có SV đăng ký.
Câu 12Câu 15Câu 45
Subquery kiểm tra hoàn thành / chưa học (tiên quyết, CTDT)
So sánh tập HP cần học với tập HP đã học của một SV cụ thể
  • Đề hỏi SV "đã đủ tiên quyết chưa" hoặc "chưa hoàn thành HP nào".
  • Cần so sánh 2 tập: (HP cần) MINUS (HP đã đạt) → phần còn lại là chưa học.
  • Có thể dùng NOT IN + subquery hoặc EXCEPT.
-- Kiểm tra tiên quyết: HP tiên quyết mà SV chưa đạt
SELECT tq.MaHPTQ
FROM   TienQuyet tq
WHERE  tq.MaHP = 'MaHocPhan'
  AND  tq.MaHPTQ NOT IN (
    SELECT lhpsv.MaHP
    FROM   LopHocPhan_SinhVien lhpsv
    WHERE  lhpsv.MaSV      = 'MaSinhVien'
      AND  lhpsv.DiemTKHP >= 4
  );
-- Nếu không có hàng trả về → đã đủ tiên quyết

-- HP trong CTDT chưa đăng ký hoặc điểm < 4
SELECT hp.MaHP, hp.TenHP
FROM   CTDT_HocPhan ctdthp
JOIN   HocPhan hp ON ctdthp.MaHP = hp.MaHP
WHERE  ctdthp.MaCTDT = (SELECT MaCTDT FROM SinhVien
                          WHERE MaSV = 'MaSV')
  AND  hp.MaHP NOT IN (
    SELECT MaHP FROM LopHocPhan_SinhVien
    WHERE  MaSV = 'MaSV' AND DiemTKHP >= 4
  );
Câu 12 SV '212606016' đã học đủ HP tiên quyết của 'IE3.003.3' chưa.
Câu 15 HP chưa hoàn thành (dưới 4 hoặc chưa đăng ký) của SV '212606016'.
Câu 45 HP trong CTDT mà SV chưa đăng ký.
Câu 18Câu 23
Subquery vô hướng — so sánh điểm với trung bình / ngưỡng
WHERE điểm < (SELECT AVG(điểm) FROM ...) hoặc điểm < ngưỡng cố định
  • Đề yêu cầu "dưới điểm trung bình của lớp", "nhỏ hơn TB".
  • Subquery trả về một giá trị duy nhất (scalar) để so sánh.
  • Cùng bảng, cùng LHP → subquery có WHERE lọc LHP giống truy vấn ngoài.
SELECT sv.MaSV, sv.HoTen, lhpsv.DiemTKHP
FROM   LopHocPhan_SinhVien lhpsv
JOIN   SinhVien sv ON sv.MaSV = lhpsv.MaSV
WHERE  lhpsv.MaHP  = 'MaHP'
  AND  lhpsv.MaLHP = 'MaLHP'
  AND  lhpsv.DiemTKHP < (
    SELECT AVG(DiemTKHP)
    FROM   LopHocPhan_SinhVien
    WHERE  MaHP = 'MaHP' AND MaLHP = 'MaLHP'
  );
Câu 18 SV có DiemTKHP < TB của LHP 'IT1.110.3' — '1-2-22-QT08'.
Câu 23 SV có điểm < 4 trong LHP cụ thể.
✏️
UPDATE / DELETE
Cập nhật dữ liệu tính toán và xóa bản ghi thỏa điều kiện
Câu 4, 5, 6, 7, 38
Câu 4Câu 38
UPDATE cột tính toán từ dữ liệu hiện có (DiemTKHP, LanHoc)
Tính giá trị mới dựa trên các cột trong cùng bảng hoặc bảng khác
  • Đề có "cập nhật cột...", "tính và lưu lại".
  • Giá trị mới = biểu thức toán học trên các cột đã có (DiemQT * 0.4 + ...).
  • Nếu cần join bảng khác để tính → dùng UPDATE ... FROM ... JOIN.
-- Câu 4: Tính DiemTKHP = DiemQT * TrọngSo + DiemThi * TrọngSo
UPDATE LopHocPhan_SinhVien
SET    DiemTKHP = ROUND(DiemQT * 0.4 + DiemThi * 0.6, 1)
WHERE  DiemQT  IS NOT NULL
  AND  DiemThi IS NOT NULL;

-- Câu 38: Cập nhật LanHoc = thứ tự học theo thời gian
UPDATE t
SET    t.LanHoc = sub.LanHoc
FROM   LopHocPhan_SinhVien t
JOIN   (
  SELECT MaSV, MaHP, MaLHP,
         ROW_NUMBER() OVER (
           PARTITION BY MaSV, MaHP
           ORDER BY NamHoc, HocKy       -- cần join LopHocPhan
         ) AS LanHoc
  FROM   LopHocPhan_SinhVien lhpsv2
  JOIN   LopHocPhan lhp ON lhpsv2.MaHP = lhp.MaHP
                         AND lhpsv2.MaLHP = lhp.MaLHP
) sub ON t.MaSV = sub.MaSV AND t.MaHP = sub.MaHP
       AND t.MaLHP = sub.MaLHP;
Câu 4 Tính và lưu cột DiemTKHP cho bảng LopHocPhan_SinhVien.
Câu 38 Cập nhật LanHoc dựa theo thứ tự thời gian của cùng một HP.
Câu 5
UPDATE điều kiện CASE WHEN — chuyển đổi bảng quy đổi điểm
Gán giá trị theo khoảng (hệ 4, hệ chữ) bằng CASE WHEN lồng nhau
  • Đề cung cấp bảng quy đổi điểm (thang điểm → hệ chữ / hệ 4).
  • Mỗi khoảng điểm → một giá trị cố định.
  • Dấu hiệu: cập nhật hai cột trở lên cùng một lúc theo cùng điều kiện khoảng.
UPDATE LopHocPhan_SinhVien
SET
  DiemHe4 = CASE
    WHEN DiemTKHP >= 9.5               THEN 4.0
    WHEN DiemTKHP >= 8.5               THEN 3.8
    WHEN DiemTKHP >= 8.0               THEN 3.5
    WHEN DiemTKHP >= 7.0               THEN 3.0
    WHEN DiemTKHP >= 6.0               THEN 2.5
    WHEN DiemTKHP >= 5.5               THEN 2.0
    WHEN DiemTKHP >= 5.0               THEN 1.5
    WHEN DiemTKHP >= 4.0               THEN 1.0
    WHEN DiemTKHP >= 3.0               THEN 0.5
    ELSE 0
  END,
  DiemHeChu = CASE
    WHEN DiemTKHP >= 9.5 THEN 'A+'
    WHEN DiemTKHP >= 8.5 THEN 'A'
    -- ... tương tự ...
    ELSE 'F'
  END
WHERE DiemTKHP IS NOT NULL;
Câu 5 Cập nhật DiemHe4, DiemHeChu theo bảng quy đổi cho tất cả SV.
Câu 6Câu 7
DELETE / UPDATE đơn giản theo điều kiện WHERE
Xóa bản ghi không thỏa điều kiện, cập nhật thông tin cụ thể một bản ghi
  • Đề có "xóa những... không có..." → DELETE + NOT EXISTS/subquery.
  • Đề có "cập nhật địa chỉ/SĐT cho SV mã..." → UPDATE + WHERE PK.
  • Đây là dạng DML đơn giản nhất, không cần GROUP BY hay window function.
-- Câu 6: Xóa LHP không có SV
DELETE FROM LopHocPhan
WHERE NOT EXISTS (
  SELECT 1 FROM LopHocPhan_SinhVien lhpsv
  WHERE  lhpsv.MaHP  = LopHocPhan.MaHP
    AND  lhpsv.MaLHP = LopHocPhan.MaLHP
);

-- Câu 7: Cập nhật thông tin SV cụ thể
UPDATE SinhVien
SET    DiaChi = N'DiaChi mới',
       SoDienThoai = 'SDT mới'
WHERE  MaSV = '201200043';
Câu 6 Xóa LHP không có SV đăng ký.
Câu 7 Cập nhật địa chỉ và SĐT cho SV '201200043'.
🧮
CTE / Tính Toán Phức Tạp
Điểm tích lũy, tổng tín chỉ, công thức nhiều bước
Câu 11, 17, 27, 33, 34, 35, 36
Câu 11Câu 14Câu 35Câu 36
GPA / Điểm tích lũy — SUM(Điểm × TínChỉ) / SUM(TínChỉ)
Tính điểm tích lũy có trọng số theo công thức chuẩn
  • Đề có "điểm tích lũy", "GPA", "điểm trung bình tích lũy".
  • Công thức: SUM(Diem × SoTinChi) / SUM(SoTinChi).
  • Lưu ý: nếu học lại thì lấy điểm cao nhất → cần MAX(DiemTKHP) trước khi tính.
  • Nên dùng CTE để tính điểm cao nhất mỗi HP trước.
WITH DiemCaoNhat AS (
  SELECT MaSV, MaHP,
         MAX(DiemTKHP) AS DiemMax
  FROM   LopHocPhan_SinhVien
  WHERE  MaSV = 'MaSV'
    AND  DiemTKHP IS NOT NULL
  GROUP BY MaSV, MaHP
)
SELECT
  d.MaSV,
  ROUND(
    SUM(d.DiemMax * hp.SoTinChi)
    / SUM(hp.SoTinChi), 2
  ) AS DiemTichLuy
FROM   DiemCaoNhat d
JOIN   HocPhan hp ON d.MaHP = hp.MaHP
GROUP BY d.MaSV;
Câu 11 Tính điểm tích lũy SV '201200085'.
Câu 14 Điểm tích lũy TB của SV CNTT theo CTDT.
Câu 35 Danh sách điểm tích lũy SV lớp CNTT CLC Việt-Anh 2 khóa 62.
Câu 36 Top 10 SV điểm tích lũy cao nhất khóa 61.
Câu 17Câu 27Câu 33
Tổng tín chỉ tích lũy — SUM tín chỉ các HP đạt (≥ 4)
Đếm số tín chỉ đã hoàn thành của SV, lọc theo điều kiện đạt
  • Đề yêu cầu "tổng số tín chỉ tích lũy", "số TC đã hoàn thành".
  • Điều kiện: HP đạt = DiemTKHP ≥ 4 (không tính trượt).
  • Nếu học lại: lấy điểm cao nhất → MAX trước SUM.
WITH HPDat AS (
  SELECT lhpsv.MaSV, lhpsv.MaHP,
         MAX(lhpsv.DiemTKHP) AS DiemMax
  FROM   LopHocPhan_SinhVien lhpsv
  WHERE  lhpsv.MaSV = 'MaSV'
  GROUP BY lhpsv.MaSV, lhpsv.MaHP
  HAVING MAX(lhpsv.DiemTKHP) >= 4
)
SELECT h.MaSV,
       SUM(hp.SoTinChi) AS TongTinChiTichLuy
FROM   HPDat h
JOIN   HocPhan hp ON h.MaHP = hp.MaHP
GROUP BY h.MaSV;
Câu 17 Tổng TC tích lũy của SV '212606016' (DiemTKHP ≥ 4).
Câu 27 Tổng TC tích lũy của từng SV.
Câu 33 Danh sách HP đạt (≥ 4) của SV '201200085'.
🪟
Window Function
RANK, ROW_NUMBER, DENSE_RANK, MAX OVER PARTITION
Câu 20, 22, 28, 37, 39, 42
Câu 20Câu 22Câu 39
Lấy bản ghi có điểm MAX theo nhóm (PARTITION BY)
Tìm SV điểm cao nhất mỗi LHP, không dùng GROUP BY thuần
  • Đề yêu cầu "điểm cao nhất của LHP", "đạt điểm cao nhất trong từng LHP".
  • Có thể có nhiều SV đồng điểm cao nhất → cần giữ tất cả → dùng RANK() hoặc so sánh với MAX.
  • Không thể GROUP BY đơn giản vì cần giữ thông tin từng dòng SV.
WITH Ranked AS (
  SELECT *,
         RANK() OVER (
           PARTITION BY MaHP, MaLHP
           ORDER BY DiemTKHP DESC
         ) AS Rank
  FROM   LopHocPhan_SinhVien
  WHERE  DiemTKHP IS NOT NULL
)
SELECT r.MaSV, sv.HoTen, r.MaHP, r.MaLHP, r.DiemTKHP
FROM   Ranked r
JOIN   SinhVien sv ON sv.MaSV = r.MaSV
WHERE  r.Rank = 1;            -- lấy điểm cao nhất, giữ đồng hạng

💡 RANK() giữ đồng hạng. ROW_NUMBER() chỉ lấy 1 dòng. Chọn theo yêu cầu.

Câu 20 SV điểm TKHP cao nhất LHP 'IT1.110.3' — '1-2-22-QT08'.
Câu 22 SV điểm cao nhất trong từng LHP (tất cả LHP).
Câu 39 SV có DiemTKHP cao nhất trong LHP 'LHP002'.
Câu 28Câu 42
RANK() xếp hạng theo nhóm / tìm người dạy nhiều nhất
Xếp hạng SV theo GPA trong lớp, hoặc GV dạy nhiều LHP nhất
  • Đề có "xếp hạng", "thứ hạng", "rank" trong từng nhóm (lớp, khoa).
  • Cần PARTITION BY nhóm, ORDER BY tiêu chí.
  • Dạng "dạy nhiều nhất": tính count trước (CTE/subquery), rồi lọc max.
-- Câu 42: Xếp hạng SV theo GPA trong từng lớp
WITH GPA AS (
  -- tính GPA ở đây...
)
SELECT
  g.MaSV, sv.HoTen, sv.MaLop,
  g.GPA,
  RANK() OVER (
    PARTITION BY sv.MaLop
    ORDER BY g.GPA DESC
  ) AS XepHang
FROM   GPA g
JOIN   SinhVien sv ON sv.MaSV = g.MaSV;

-- Câu 28: GV dạy nhiều LHP nhất HK2 2023-2024
WITH Count_LHP AS (
  SELECT MaGV, COUNT(*) AS SoLHP
  FROM   LopHocPhan
  WHERE  NamHoc = '2023-2024' AND HocKy = 2
  GROUP BY MaGV
)
SELECT * FROM Count_LHP
WHERE  SoLHP = (SELECT MAX(SoLHP) FROM Count_LHP);
Câu 28 GV dạy nhiều LHP nhất HK2 2023-2024.
Câu 42 Xếp hạng SV theo GPA trong từng lớp.
Câu 37
TOP-N trong mỗi nhóm — 5 SV học bổng mỗi lớp
Lấy N bản ghi đứng đầu theo nhóm (PARTITION BY lớp)
  • Đề yêu cầu "top N trong mỗi lớp/nhóm".
  • Khác TOP N toàn bảng — phải dùng ROW_NUMBER() hoặc RANK() với PARTITION BY.
WITH GPA_Ranked AS (
  -- ... tính GPA cho mỗi SV ...
),
Ranked AS (
  SELECT g.*,
         DENSE_RANK() OVER (
           PARTITION BY sv.MaLop
           ORDER BY g.GPA DESC
         ) AS Rank
  FROM   GPA_Ranked g
  JOIN   SinhVien sv ON sv.MaSV = g.MaSV
)
SELECT * FROM Ranked
WHERE  Rank <= 5;   -- top 5 mỗi lớp
Câu 37 5 SV điểm tích lũy cao nhất ở mỗi lớp (học bổng).
📅
Date / Điều Kiện Đặc Biệt
MONTH(), GETDATE(), điều kiện thời gian và tháng hiện tại
Câu 16, 41
Câu 16Câu 41
Lọc theo tháng hiện tại / học kỳ cụ thể
Dùng MONTH(GETDATE()) hoặc điều kiện NamHoc + HocKy để lọc thời gian
  • Đề có cụm "sinh nhật trong tháng hiện tại"MONTH(NgaySinh) = MONTH(GETDATE()).
  • Đề có "học kỳ 1 năm học 2024"HocKy = 1 AND NamHoc LIKE '%2024%'.
  • UNION nếu cần kết hợp nhiều bảng (SV + GV có cùng trường NgaySinh).
-- Câu 16: SV + GV sinh nhật tháng hiện tại
SELECT 'SinhVien' AS LoaiNguoi,
       MaSV AS MaID, HoTen, NgaySinh
FROM   SinhVien sv
JOIN   Lop lp ON sv.MaLop = lp.MaLop
JOIN   Khoa  k  ON lp.MaKhoa = k.MaKhoa
WHERE  k.TenKhoa LIKE N'%Công nghệ thông tin%'
  AND  MONTH(sv.NgaySinh) = MONTH(GETDATE())

UNION ALL

SELECT 'GiangVien',
       MaGV, HoTen, NgaySinh
FROM   GiangVien gv
JOIN   BoMon bm ON gv.MaBM = bm.MaBM
JOIN   Khoa  k  ON bm.MaKhoa = k.MaKhoa
WHERE  k.TenKhoa LIKE N'%Công nghệ thông tin%'
  AND  MONTH(gv.NgaySinh) = MONTH(GETDATE());
Câu 16 SV + GV Khoa CNTT có sinh nhật trong tháng hiện tại.
Câu 41 Trưởng bộ môn dạy ít nhất 1 LHP trong HK1 năm học 2024.
🏆
TOP-N / Xếp Hạng Toàn Bảng
SELECT TOP, ORDER BY, điểm cao nhất / nhiều nhất toàn bộ
Câu 31, 32, 36, 40, 43
Câu 31Câu 32
Tìm HP / LHP có giá trị MAX theo tiêu chí
Tính metric theo nhóm rồi lọc nhóm có giá trị MAX
  • Đề có "nhiều nhất", "cao hơn các HP khác", "số SV dưới 4 nhiều nhất".
  • Tính metric (COUNT, AVG...) theo nhóm → lọc bằng WHERE metric = MAX(metric).
  • Dùng CTE để tính metric, rồi truy vấn lọc WHERE = max của CTE.
WITH SoDuoi4 AS (
  SELECT MaHP, COUNT(*) AS SoSVDuoi4
  FROM   LopHocPhan_SinhVien
  WHERE  DiemTKHP < 4
  GROUP BY MaHP
)
SELECT MaHP, SoSVDuoi4
FROM   SoDuoi4
WHERE  SoSVDuoi4 = (
  SELECT MAX(SoSVDuoi4) FROM SoDuoi4
);
Câu 31 HP CNTT có điểm tích lũy cao hơn tất cả HP khác trong HK2 2023-2024.
Câu 32 HP có số SV điểm dưới 4 nhiều nhất.
Câu 40Câu 43
HAVING COUNT ≥ N / Kiểm tra "tất cả" với COUNT = tổng điều kiện
Lọc GV dạy ≥ 3 LHP; kiểm tra SV hoàn thành tất cả HP bắt buộc
  • Đề có "từ N trở lên", "ít nhất N"HAVING COUNT(*) >= N.
  • Đề có "tất cả HP bắt buộc" → đếm HP đạt của SV = đếm HP bắt buộc trong CTDT → COUNT đạt = COUNT tổng.
-- Câu 40: GV dạy từ 3 LHP trở lên năm học 2023-2024
SELECT gv.MaGV, gv.HoTen, COUNT(lhp.MaLHP) AS SoLHP
FROM   GiangVien gv
JOIN   LopHocPhan lhp ON gv.MaGV = lhp.MaGV
WHERE  lhp.NamHoc = '2023-2024'
GROUP BY gv.MaGV, gv.HoTen
HAVING COUNT(lhp.MaLHP) >= 3;

-- Câu 43: SV hoàn thành TẤT CẢ HP bắt buộc
SELECT sv.MaSV, sv.HoTen
FROM   SinhVien sv
JOIN   CTDT_HocPhan ctdthp
       ON ctdthp.MaCTDT = sv.MaCTDT
      AND ctdthp.BatBuoc = 1
LEFT JOIN LopHocPhan_SinhVien lhpsv
       ON lhpsv.MaSV  = sv.MaSV
      AND lhpsv.MaHP  = ctdthp.MaHP
      AND lhpsv.DiemTKHP >= 4
GROUP BY sv.MaSV, sv.HoTen, sv.MaCTDT
HAVING
  COUNT(lhpsv.MaHP)       -- số HP bắt buộc đã đạt
  = (SELECT COUNT(*) FROM CTDT_HocPhan
     WHERE MaCTDT = sv.MaCTDT AND BatBuoc = 1);
Câu 40 GV dạy từ 3 LHP trở lên trong năm học 2023-2024.
Câu 43 SV đã đạt tất cả HP bắt buộc trong CTDT của mình.