Học bằng cách đọc theo thứ tự

Hàm ⑤ — CASE để rẽ nhánh nhiều điều kiện

Bài thứ năm về hàm SQL. Hai dạng CASE (dạng đơn giản và dạng tìm kiếm), từ ba nhánh trở lên, kết hợp với hàm và điều kiện ghép, và ghép cùng ORDER BY — trên tập dữ liệu staff được tải từ CSV.

Dữ liệu dùng trong bài này — bảng staff

IIF ở bài trước chỉ có một điều kiện, nên chỉ rẽ nhánh hai chiều đúng/sai. Biểu thức CASE trong bài này xét ba điều kiện trở lên theo thứ tự và có thể trả về một giá trị khác cho mỗi điều kiện. Đây là cú pháp cơ bản để viết "if-elseif-else" bên trong SQL, và là cấu trúc rẽ nhánh phổ biến nhất trong công việc thực tế — phân loại báo cáo, gom nhóm theo vùng, xếp hạng điểm, v.v.

Đối tượng vẫn là bảng staff (10 hàng) như trước. Qua các bài thực hành dựng phân loại vùng trên cột city, phân loại khoảng lương trên salary, và phân loại thế hệ trên birthday, bạn sẽ lần lượt thử hai dạng CASE và ứng dụng của chúng cho điều kiện ghép.

Trước khi bắt đầu các bài thực hành, hãy xác nhận định nghĩa cộtdữ liệu mẫu của bảng staff.

① Chạy PRAGMA table_info(staff); để xem tên cột, kiểu và khóa chính.

② Chạy SELECT * FROM staff LIMIT 5; để xem trước 5 hàng đầu.

SQL Editor

Chạy truy vấn để xem kết quả

CASE có hai cách viết

Biểu thức CASE có hai dạng — dạng đơn giảndạng tìm kiếm — và cả hai đều cho ra cùng kết quả. Có hai quy tắc chung cho cả hai.

  • `END` cuối cùng là bắt buộc — quên nó sẽ gây lỗi cú pháp.
  • `ELSE` là tùy chọn — nếu bỏ qua, các hàng không khớp WHEN nào sẽ thành NULL. Để tránh NULL, hãy nêu rõ giá trị mặc định bằng ELSE.

Dạng ① Dạng đơn giản — So sánh bằng trên một cột

Dạng đơn giản viết là CASE cột WHEN giá_trị1 THEN kết_quả1 WHEN giá_trị2 THEN kết_quả2 ... ELSE mặc_định END. Ngay sau CASE bạn đặt một cột để so sánh, và bên phải WHEN bạn viết một giá trị để kiểm tra cột có bằng hay không. Phép kiểm tra chỉ là so sánh bằng (`=`), và bên phải WHEN bạn chỉ viết được một giá trị duy nhất — không cho phép nhiều giá trị như WHEN ('Tokyo', 'Osaka'). Nó hợp với phép thay thế đơn giản cột = giá trị và viết ngắn hơn.

Rẽ nhánh ở dạng đơn giản
cột mục tiêugiá trị WHENgiá trị trả vềCASE city= 'Tokyo'= 'Osaka'ELSE'TOK''OSA'city gốc
CASE city nhìn vào một cột và làm so sánh bằng với mỗi giá trị WHEN. Giá trị THEN của WHEN khớp sẽ được trả về; nếu không khớp cái nào, giá trị ELSE được dùng.
-- Dạng đơn giản — thay city bằng tên vùng
SELECT name, city,
  CASE city
    WHEN 'Tokyo' THEN 'Kanto'
    WHEN 'Yokohama' THEN 'Kanto'
    WHEN 'Osaka' THEN 'Kansai'
    WHEN 'Kyoto' THEN 'Kansai'
    ELSE 'Other'
  END AS region
FROM staff;

Hãy hình dung yêu cầu "hiển thị cột city dưới dạng mã ngắn". (Lời giải hiện ra khi bạn chạy đúng.)

① Từ bảng staff, lấy namecity.

② Dùng dạng CASE đơn giản, thêm cột thứ 3 đặt bí danh city_code là 'TOK' nếu city là Tokyo, 'OSA' nếu Osaka, 'KYO' nếu Kyoto, 'YOK' nếu Yokohama, 'SAP' nếu Sapporo, và giá trị city gốc nếu không khớp cái nào.

SQL Editor

Chạy truy vấn để xem kết quả

Dạng ② Dạng tìm kiếm — Viết điều kiện bất kỳ một cách tự do

Dạng tìm kiếm viết là CASE WHEN bt1 THEN kết_quả1 WHEN bt2 THEN kết_quả2 ... ELSE mặc_định END. Ngay sau CASE bạn không viết gì cả, và bên phải mỗi WHEN bạn đặt chính điều kiện đó. Toán tử so sánh như salary >= 6000000, LIKE như name LIKE '%Tanaka', IN, và điều kiện ghép AND / OR — bất cứ thứ gì viết được trong WHERE đều dùng được ở đây. WHEN được đánh giá từ trên xuống, và giá trị được quyết định bởi nhánh đầu tiên trở thành TRUE. Vì biểu cảm mạnh nên đây là dạng chủ yếu dùng trong thực tế.

Rẽ nhánh ở dạng tìm kiếm — Đánh giá từ trên xuống
đánh giá WHEN trên-xuốngkiểm tragiá trị trả vềsalary >= 6000000salary >= 4500000ELSEnếu TRUEnếu TRUEtất cả còn lại'Senior''Mid''Junior'FALSEFALSE
WHEN được đánh giá từ trên xuống. Khi một điều kiện TRUE, giá trị THEN được chốt và không kiểm tra thêm. Nếu FALSE thì rơi xuống WHEN kế; nếu tất cả FALSE, giá trị ELSE được dùng.
-- Dạng tìm kiếm — chia salary thành 2 khoảng
SELECT name, salary,
  CASE
    WHEN salary >= 5000000 THEN 'High'
    ELSE 'Standard'
  END AS pay_band
FROM staff;

Hãy hình dung yêu cầu "phân loại nhân viên thành 3 bậc (Junior / Mid / Senior) theo lương".

① Từ bảng staff, lấy namesalary.

② Dùng dạng CASE tìm kiếm, thêm cột thứ 3 đặt bí danh tier'Senior' nếu salary từ 6,000,000 trở lên, 'Mid' nếu từ 4,500,000 trở lên nhưng dưới 6,000,000, và 'Junior' nếu thấp hơn nữa.

SQL Editor

Chạy truy vấn để xem kết quả

Kết hợp với hàm và điều kiện ghép để rẽ nhánh phức tạp hơn

Một mệnh đề CASE WHEN có thể chứa các biểu thức kết hợp toán tử so sánh, LIKE, IN, AND / OR, và lời gọi hàm. Bạn có thể lấy năm sinh bằng strftime('%Y', birthday) đã học ở Hàm ① hàm ngày tháng để phân loại thế hệ; vì name theo thứ tự "tên họ", name LIKE '%Tanaka' (khớp hậu tố) phân loại những người có họ là Tanaka; và bạn có thể viết điều kiện kết hợp nhiều cột với AND.

Ví dụ bên dưới lấy năm sinh theo đơn vị 10 năm và gắn nhãn người sinh thập niên 1990 là 'Gen Z' và thập niên 1980 là 'Gen X-Y'. Vì strftime trả về chuỗi, các phép so sánh được thực hiện với hằng chuỗi ('1990' / '1999').

-- 1) Gắn nhãn năm sinh theo nhóm 5 năm
SELECT name, birthday,
  CASE
    WHEN strftime('%Y', birthday) BETWEEN '1985' AND '1989' THEN 'Late 1980s'
    WHEN strftime('%Y', birthday) BETWEEN '1990' AND '1994' THEN 'Early 1990s'
    ELSE 'Other'
  END AS cohort
FROM staff;

-- 2) Điều kiện ghép: lương cao VÀ ở Tokyo
SELECT name, city, salary,
  CASE
    WHEN salary >= 6000000 AND city = 'Tokyo' THEN 'Tokyo senior'
    WHEN salary >= 6000000 THEN 'Senior'
    ELSE 'Other'
  END AS tag
FROM staff;

Hãy hình dung yêu cầu "chia toàn bộ nhân viên thành các thế hệ theo năm sinh, đơn vị 10 năm".

① Từ bảng staff, lấy namebirthday.

② Dùng dạng CASE tìm kiếm, thêm cột thứ 3 đặt bí danh generation'Gen Z' nếu năm sinh lấy từ birthday thuộc thập niên 1990, 'Gen X-Y' nếu thuộc thập niên 1980, và 'Other' nếu khác.

SQL Editor

Chạy truy vấn để xem kết quả

Hãy hình dung yêu cầu "hiển thị TOP 5 theo lương trên màn hình xếp hạng, mỗi người kèm một nhãn khoảng lương".

① Từ bảng staff, lấy namesalary.

② Dùng dạng CASE tìm kiếm, thêm cột thứ 3 đặt bí danh tier với các nhãn khoảng lương giống Thực hành 2 ('Senior' nếu salary từ 6,000,000 trở lên, 'Mid' nếu từ 4,500,000 trở lên, 'Junior' nếu khác).

③ Sắp xếp theo `salary` giảm dần và giới hạn ở 5 hàng đầu.

SQL Editor

Chạy truy vấn để xem kết quả
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1Trong các cấu trúc sau, đâu là cấu trúc biểu thức CASE đúng?

Câu 2Đâu là mô tả đúng cho dạng đơn giản CASE city WHEN 'Tokyo' THEN 'TOK' WHEN 'Osaka' THEN 'OSA' ELSE city END?

Câu 3CASE WHEN salary >= 6000000 THEN 'Senior' WHEN salary >= 4500000 THEN 'Mid' ELSE 'Junior' END trả về gì cho một hàng có salary = 7,000,000?