Cùng nói về một hàm nữa để làm việc với NULL bí ẩn — NULLIF(). Hàm này sẽ giúp tụi mình trong những tình huống cần thay thế giá trị nhất định thành NULL để xử lý dữ liệu cho chuẩn. Thắt dây an toàn đi, chuyến này vui lắm đó!
Hàm NULLIF() là một công cụ xịn sò trong PostgreSQL, cho phép bạn so sánh hai giá trị và trả về NULL nếu chúng giống nhau, hoặc trả về giá trị đầu tiên nếu chúng khác nhau. Nó kiểu như nói: "Nếu hai giá trị này giống nhau thì quên nó đi nha!"
Đây là cú pháp đơn giản của hàm:
NULLIF(value1, value2)
Nếu value1 và value2 bằng nhau thì kết quả là NULL. Nếu khác nhau thì kết quả là value1.
Ví dụ:
SELECT NULLIF(10, 10); -- Kết quả: NULL
SELECT NULLIF(10, 20); -- Kết quả: 10
SELECT NULLIF('hello', 'hello'); -- Kết quả: NULL
SELECT NULLIF('hello', 'world'); -- Kết quả: 'hello'
Dễ mà đúng không? Giờ thử áp dụng hàm này vào mấy bài toán thực tế nha.
Ví dụ 1: Tránh chia cho 0
Chia cho 0 là ác mộng của dân code luôn. Trong SQL mà chia cho 0 là lỗi liền. Đây là lúc NULLIF() cứu nguy nè.
Giả sử tụi mình có bảng sales với hai cột: revenue (doanh thu) và expenses (chi phí). Mình muốn tính tỷ suất lợi nhuận (revenue / expenses), nhưng đôi khi chi phí lại bằng 0. Nếu cứ thế mà chạy truy vấn thì sẽ bị lỗi chia cho 0.
Bảng sales:
| revenue | expenses |
|---|---|
| 1000 | 200 |
| 1500 | 0 |
| 2000 | 250 |
Truy vấn bị lỗi:
SELECT revenue / expenses AS profitability
FROM sales;
-- Lỗi: chia cho 0!
Giải pháp với NULLIF():
SELECT revenue / NULLIF(expenses, 0) AS profitability
FROM sales;
Kết quả:
| profitability |
|---|
| 5.00 |
| NULL |
| 8.00 |
Bây giờ, nếu expenses bằng 0, NULLIF(expenses, 0) trả về NULL, và chia cho NULL thì không bị lỗi mà chỉ trả về NULL thôi.
Ví dụ 2: Thay giá trị giống nhau thành NULL
Giả sử bạn có bảng thông tin sinh viên với hai cột first_name và preferred_name. Đôi khi sinh viên thích dùng tên thật, đôi khi lại chọn tên khác. Nếu hai tên giống nhau thì mình không cần hiển thị preferred_name làm gì.
Bảng students:
| first_name | preferred_name |
|---|---|
| John | Johnny |
| Anna | Anna |
| Alex | Lex |
Truy vấn với NULLIF():
SELECT first_name,
NULLIF(preferred_name, first_name) AS display_name
FROM students;
Kết quả:
| first_name | display_name |
|---|---|
| John | Johnny |
| Anna | NULL |
| Alex | Lex |
Khi preferred_name và first_name giống nhau thì kết quả là NULL.
Ví dụ 3: Lọc dữ liệu
Đôi khi bạn chỉ muốn lấy những dòng mà hai cột có giá trị khác nhau. Ví dụ, có bảng đơn hàng với original_price và discounted_price. Mình cần tìm đơn hàng đã được giảm giá.
Bảng orders:
| order_id | original_price | discounted_price |
|---|---|---|
| 1 | 100 | 100 |
| 2 | 200 | 180 |
| 3 | 150 | 150 |
Truy vấn với NULLIF():
SELECT order_id, original_price, discounted_price
FROM orders
WHERE NULLIF(original_price, discounted_price) IS NOT NULL;
Kết quả:
| order_id | original_price | discounted_price |
|---|---|---|
| 2 | 200 | 180 |
Chỉ những đơn hàng có giảm giá mới xuất hiện trong kết quả.
Case thực tế dùng NULLIF()
Case 1: Chọn giá trị tuỳ chọn
Khi làm việc với dữ liệu, đôi lúc bạn cần chọn giá trị từ nhiều cột, loại trừ những giá trị bằng một giá trị nhất định. Ví dụ, có danh sách nhân viên với lương: base_salary và bonus. Nếu bonus bằng 0 thì mình muốn set nó thành 999.
Bảng employees:
| employee_id | base_salary | bonus |
|---|---|---|
| 1 | 50000 | 10000 |
| 2 | 40000 | 0 |
| 3 | 60000 | 5000 |
Truy vấn với NULLIF():
SELECT employee_id,
base_salary + COALESCE(NULLIF(bonus, 0), 999) AS total_salary
FROM employees;
Kết quả:
| employee_id | total_salary |
|---|---|
| 1 | 60000 |
| 2 | 40999 |
| 3 | 65000 |
Nếu bonus bằng 0 thì nó sẽ thành 999.
Case 2: Đếm số dòng
Tụi mình có thể dùng NULLIF() để đơn giản hoá điều kiện lọc phức tạp. Ví dụ, có bảng users và muốn đếm tổng số user và số user đã đăng ký (không phải guest) chỉ với một truy vấn.
SELECT
COUNT(*) AS total_users,
COUNT(NULLIF(status, 'guest')) AS registered_users
FROM users;
Chỉ với một hàm NULLIF() thôi mà giải quyết được bao nhiêu bài toán: từ tránh lỗi tới làm code dễ đọc hơn. Giờ bạn đã biết cách dùng nó rồi, lại gần hơn một bước tới trình cao thủ dữ liệu trong PostgreSQL rồi đó!
GO TO FULL VERSION