DHDataHọc
TheoryLesson 8/306 min read+10 XP

So sánh số

Bạn sẽ học được

  • Dùng sáu toán tử so sánh số và biết khi nào dùng <> thay cho !=.
  • Viết literal số đúng cách, không dấu chấm ngăn cách và không dấu nháy.
  • Dùng BETWEEN đúng với biên trên và biên dưới.
  • Kiểm tra một điều kiện số bằng cách đối chiếu với dữ liệu gốc.
  • Nhận ra các lỗi khiến phép so sánh chạy được nhưng trả sai kết quả.

Khái niệm cốt lõi

So sánh số là dạng lọc cơ bản nhất. Có sáu toán tử:

Toán tửNghĩaVí dụ trên products.price
=bằngprice = 890000
<>khácprice <> 890000
>lớn hơnprice > 1000000
>=lớn hơn hoặc bằngprice >= 1000000
<nhỏ hơnprice < 300000
<=nhỏ hơn hoặc bằngprice <= 300000

PostgreSQL cũng chấp nhận != như một cách viết khác của <>. Cả hai cho cùng kết quả. Tuy vậy, <> là chuẩn SQL và xuất hiện trong hầu hết tài liệu, nên hãy chọn một kiểu và giữ nhất quán — thường là <>.

Literal số viết trực tiếp, không có dấu nháy và không có dấu chấm ngăn cách hàng nghìn:

code
-- Đúng
SELECT name FROM products WHERE price >= 1000000;

-- Sai: Postgres hiểu '1.000.000' là chuỗi
SELECT name FROM products WHERE price >= '1.000.000';

Câu thứ hai có thể báo lỗi hoặc trả kết quả sai tùy ngữ cảnh, vì '1.000.000' không phải một số hợp lệ theo định dạng PostgreSQL. Đây là lỗi rất Việt Nam: chúng ta quen viết 1.000.000 với dấu chấm, còn SQL dùng dấu chấm làm dấu thập phân. Trong SQL, một triệu là 1000000, còn 1.000000 là một phẩy không.

BETWEEN a AND b là cách viết gọn cho >= a AND <= b. Cả hai biên đều bao gồm:

code
SELECT name, price
FROM products
WHERE price BETWEEN 300000 AND 900000;

Tương đương:

code
SELECT name, price
FROM products
WHERE price >= 300000 AND price <= 900000;

Có hai cái bẫy. Thứ nhất, đặt ngược biên — BETWEEN 900000 AND 300000 — trả về 0 dòng chứ không báo lỗi, vì không số nào vừa lớn hơn 900000 vừa nhỏ hơn 300000. Thứ hai, quên rằng biên trên bao gồm: nếu muốn "dưới 900000" thì phải viết < 900000, không dùng BETWEEN.

Với số thực (numeric, double precision), so sánh bằng = có thể gây bất ngờ vì sai số biểu diễn. Với cột price numeric(12,2) trong dữ liệu này thì an toàn, nhưng khi tính toán với double precision, hãy so sánh trong một khoảng thay vì bằng tuyệt đối. Đây là lý do các hệ thống tài chính dùng numeric thay vì số thực.

Cuối cùng, số và NULL không so sánh được bằng các toán tử trên. price = NULL trả về unknown, không phải true, nên không dòng nào được chọn. Muốn kiểm tra NULL, dùng IS NULL. Chủ đề này có bài riêng ở cuối chương, nhưng cần biết trước để không ngạc nhiên khi thấy kết quả rỗng.

Ví dụ chạy được

Bảng products có 9 sản phẩm với giá từ 180.000 đến 1.690.000. Lấy các sản phẩm từ 500.000 trở lên:

code
SELECT id, name, price
FROM products
WHERE price >= 500000
ORDER BY price;

Ba dòng:

idnameprice
1Tai nghe Bluetooth890000
2Bàn phím cơ1250000
3Nồi chiên không dầu1690000

Đổi chiều so sánh, lấy các sản phẩm dưới 500.000:

code
SELECT name, price
FROM products
WHERE price < 500000
ORDER BY price;

Sáu dòng: Sách SQL thực chiến (180000), Áo thun cotton (250000), Đèn bàn LED (290000), Bình giữ nhiệt (320000), Giá kê laptop (390000), Chuột không dây (450000).

Ba cộng sáu bằng chín, đúng bằng số sản phẩm. Đây là phép kiểm tra quen thuộc: hai điều kiện bù trừ (>= 500000 và < 500000) phải phủ toàn bộ bảng. Nếu thiếu một sản phẩm, có thể bạn đã dùng > 500000 ở một bên và > 500000 ở bên kia, để lọt đúng mức 500.000.

Dùng BETWEEN cho khoảng giá trung bình:

code
SELECT name, price
FROM products
WHERE price BETWEEN 300000 AND 900000
ORDER BY price;

Bốn dòng: Bình giữ nhiệt (320000), Giá kê laptop (390000), Chuột không dây (450000), Tai nghe Bluetooth (890000). Sản phẩm 1.250.000 và 1.690.000 nằm ngoài khoảng; sản phẩm 290.000 cũng ngoài vì nhỏ hơn biên dưới 10.000.

Một ví dụ trên cột số nguyên, stock:

code
SELECT name, stock
FROM products
WHERE stock >= 10
ORDER BY stock DESC;

Sáu dòng: Áo thun cotton (40), Sách SQL thực chiến (30), Tai nghe Bluetooth (25), Chuột không dây (18), Đèn bàn LED (12), Bàn phím cơ (10). Bàn phím cơ đúng bằng 10 nên được chọn — >= bao gồm biên. Bình giữ nhiệt có stock = 0 bị loại; ba sản phẩm còn lại có tồn kho dưới 10 cũng bị loại.

Một thói quen tốt: khi viết điều kiện biên, luôn tự hỏi "giá trị đúng bằng biên thì sao?". Với >= và <=, nó được chọn; với > và <, nó bị loại. Chỉ một ký tự khác nhau nhưng thay đổi kết quả, và trong báo cáo kinh doanh, một sản phẩm bị lọt có thể làm sai toàn bộ doanh thu.

Thực hành

  1. Viết truy vấn lấy các sản phẩm có giá trên 1.000.000. Kết quả phải là hai dòng (Bàn phím cơ, Nồi chiên không dầu). Sau đó đổi thành >= 1000000 và xác nhận kết quả không đổi — vì không sản phẩm nào đúng bằng 1.000.000.
  2. Lấy các sản phẩm còn hàng bằng stock <> 0. Kết quả tám dòng. Thử stock > 0 và so sánh: với dữ liệu này hai cách cho cùng kết quả, nhưng > 0 rõ ý hơn khi nói về "còn hàng".
  3. Viết truy vấn lấy các đơn có id từ 5 đến 10 bằng BETWEEN. Kết quả sáu dòng. Đổi thành id > 5 AND id < 10 và đếm lại: còn bốn dòng, vì hai biên bị loại.
  4. Tự đặt một khoảng giá, dự đoán danh sách sản phẩm, rồi chạy để đối chiếu. Làm ba lần với ba khoảng khác nhau; đây là cách luyện đọc dữ liệu nhanh.

Lỗi thường gặp

Triệu chứngNguyên nhânCách sửa
invalid input syntax for type numeric: "1.000.000"Dùng dấu chấm ngăn cách hàng nghìnViết 1000000, không nháy
Truy vấn trả 0 dòng dù khoảng có dữ liệuĐặt ngược biên trong BETWEENĐặt biên nhỏ trước, lớn sau
Kết quả thiếu đúng giá trị biênDùng >/< thay vì >=/<=Thêm dấu = nếu muốn bao gồm biên
So sánh với NULL không trả dòng nào= NULL luôn là unknownDùng IS NULL hoặc IS NOT NULL
operator does not exist: numeric = textSo sánh cột số với chuỗi không chuyển đượcBỏ dấu nháy quanh số

Lỗi đầu tiên đặc biệt phổ biến với người mới vì thói quen viết số tiếng Việt. Hãy nhớ: trong SQL, dấu chấm là dấu thập phân, dấu phẩy ngăn cách đối số hàm. Không có dấu phân cách hàng nghìn.

Lỗi cuối cùng ít gặp hơn nhưng đáng biết: PostgreSQL có thể báo operator does not exist khi hai bên không cùng kiểu và không có chuyển đổi ngầm. Đây là tín hiệu tốt — nó buộc bạn viết đúng kiểu thay vì để cơ sở dữ liệu đoán.

Tóm tắt

  • Sáu toán tử: =, <>, >, >=, <, <=; != cũng chạy nhưng <> là chuẩn.
  • Literal số không nháy, không dấu chấm ngăn cách hàng nghìn.
  • BETWEEN a AND b bao gồm cả hai biên và tương đương >= a AND <= b.
  • Hai điều kiện bù trừ phải phủ toàn bộ bảng — dùng phép đếm để kiểm tra.
  • NULL không so sánh được bằng toán tử; dùng IS NULL.

Use ← → to move between lessons