0

Trino SQL Bài học 15: Biểu thức điều kiện rẽ nhánh (CASE WHEN và IF)

Mục tiêu bài học:

  • Hiểu cách áp dụng logic lập trình cơ bản (If-Else) ngay bên trong câu truy vấn SQL.

  • Phân biệt và sử dụng đúng lúc hàm IF() (nhanh, gọn) và mệnh đề CASE WHEN (đa luồng, linh hoạt).

  • Ứng dụng để phân loại, gán nhãn dữ liệu (Data Binning) và làm sạch kết quả hiển thị.

  • Tránh các cạm bẫy về thứ tự thực thi điều kiện.

1. Hàm IF(): Giải pháp nhanh cho logic nhị phân

Trong các hệ thống RDBMS truyền thống (như SQL Server), bạn thường phải dùng CASE WHEN cho mọi logic rẽ nhánh. Tuy nhiên, Trino cung cấp hàm IF() để xử lý các bài toán rẽ nhánh đơn giản (chỉ có 2 trường hợp Đúng/Sai) giúp cú pháp ngắn gọn hơn rất nhiều.

Cú pháp: IF(điều_kiện, giá_trị_nếu_đúng, [giá_trị_nếu_sai]) (Lưu ý: Nếu không truyền tham số thứ 3, Trino sẽ mặc định trả về NULL khi điều kiện sai).

Ứng dụng thực tế: Gán nhãn đơn giản Gắn cờ (flag) cho các đơn hàng có giá trị lớn hơn 200,000 là 'High Value', ngược lại là 'Normal'.

SQL

SELECT 
    orderkey, 
    totalprice,
    IF(totalprice > 200000, 'High Value', 'Normal') AS order_category
FROM tpch.tiny.orders
LIMIT 5;

Góc kỹ sư: Hàm IF() rất tiện, nhưng nếu bạn lồng ghép quá nhiều hàm IF() vào nhau (Nested IF), câu SQL sẽ biến thành "thảm họa" khó đọc. Khi có từ 3 nhánh logic trở lên, hãy dùng CASE WHEN.

2. Mệnh đề CASE WHEN: "Vũ khí" chuẩn ANSI SQL

CASE WHEN là cú pháp chuẩn mực, chạy được trên mọi hệ quản trị CSDL, và là cách chuyên nghiệp nhất để xử lý đa luồng logic. Nó chia làm 2 dạng: dạng linh hoạt (Searched) và dạng đối chiếu bằng (Simple).

A. Dạng 1: Searched CASE (Linh hoạt tối đa)

Đây là dạng phổ biến nhất, cho phép bạn đánh giá nhiều điều kiện khác nhau (lớn hơn, nhỏ hơn, kết hợp AND/OR).

Cú pháp:

SQL

CASE 
    WHEN điều_kiện_1 THEN kết_quả_1
    WHEN điều_kiện_2 THEN kết_quả_2
    ...
    ELSE kết_quả_mặc_định 
END

Lưu ý: Nếu bạn không viết mệnh đề ELSE, các trường hợp không thỏa mãn sẽ tự động nhận giá trị NULL.

Ví dụ: Phân khúc khách hàng dựa trên tài khoản

SQL

SELECT 
    name, 
    acctbal,
    CASE 
        WHEN acctbal < 0 THEN 'Nợ xấu'
        WHEN acctbal BETWEEN 0 AND 3000 THEN 'Tiêu chuẩn'
        WHEN acctbal > 3000 THEN 'Khách VIP'
        ELSE 'Không xác định'
    END AS customer_segment
FROM tpch.tiny.customer;

B. Dạng 2: Simple CASE (Đối chiếu bằng)

Khi bạn chỉ cần so sánh bằng (=) trên cùng một cột với nhiều giá trị khác nhau, cú pháp Simple CASE (giống như switch-case trong lập trình) sẽ giúp truy vấn gọn và dễ đọc hơn.

Ví dụ: Việt hóa trạng thái đơn hàng Thay vì viết lặp đi lặp lại WHEN orderstatus = 'O' THEN ... WHEN orderstatus = 'F' THEN ..., ta viết tên cột ngay sau chữ CASE.

SQL

SELECT 
    orderkey,
    orderstatus,
    CASE orderstatus
        WHEN 'O' THEN 'Đang mở (Open)'
        WHEN 'F' THEN 'Đã hoàn thành (Finished)'
        WHEN 'P' THEN 'Đang xử lý (Pending)'
        ELSE 'Trạng thái khác'
    END AS status_vn
FROM tpch.tiny.orders;

3. Cạm bẫy "Thứ tự thực thi" (Evaluation Order)

Quy tắc sống còn của CASE WHEN: Trino sẽ đánh giá các điều kiện từ trên xuống dưới (Top-Down). Ngay khi có một điều kiện thỏa mãn (Đúng), nó sẽ trả về kết quả đó và BỎ QUA toàn bộ các điều kiện bên dưới.

Hãy xem một lỗi logic kinh điển:

SQL

-- CÚ PHÁP SAI LOGIC CHồng chéo
SELECT 
    totalprice,
    CASE 
        WHEN totalprice > 10000 THEN 'Silver'
        WHEN totalprice > 50000 THEN 'Gold'
        WHEN totalprice > 100000 THEN 'Diamond'
    END AS tier
FROM tpch.tiny.orders;

Chuyện gì xảy ra? Một đơn hàng trị giá 150,000 (đáng lẽ phải là Diamond) khi chạy qua dòng đầu tiên (> 10000) sẽ trả về kết quả là TRUE. Trino lập tức gán mác Silver và dừng lại. Đơn hàng này không bao giờ chạm được đến dòng Gold hay Diamond.

Cách khắc phục (Best Practice): Luôn sắp xếp các điều kiện từ hẹp nhất (khó xảy ra nhất / lớn nhất) đến rộng nhất.

SQL

-- CÚ PHÁP ĐÚNG LOGIC
SELECT 
    totalprice,
    CASE 
        WHEN totalprice > 100000 THEN 'Diamond'
        WHEN totalprice > 50000 THEN 'Gold'
        WHEN totalprice > 10000 THEN 'Silver'
        ELSE 'Normal'
    END AS tier
FROM tpch.tiny.orders;

4. Ứng dụng nâng cao (Chuẩn bị cho Bài Tổng hợp)

Một kỹ thuật cực kỳ mạnh mẽ của Data Analyst là Conditional Aggregation (Tổng hợp có điều kiện) – kết hợp CASE WHEN bên trong các hàm tính toán như SUM hoặc COUNT.

Kỹ thuật này cho phép bạn tạo ra các cột "Pivot" ngay trong lệnh SELECT.

SQL

-- Đếm riêng biệt các đơn hàng khẩn cấp và đơn hàng thường trên cùng 1 dòng
SELECT 
    COUNT(CASE WHEN orderpriority = '1-URGENT' THEN 1 END) AS total_urgent,
    COUNT(CASE WHEN orderpriority <> '1-URGENT' THEN 1 END) AS total_normal
FROM tpch.tiny.orders;

(Bạn không cần hiểu sâu ngay ví dụ này, chúng ta sẽ bóc tách nó chi tiết trong các bài về Hàm tổng hợp).


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí