Đôi khi sẽ có những tình huống mà bạn cần biết một tập giá trị này có nằm trong tập khác không, hai tập có giao nhau không, có bằng nhau không, hay cái này là tập con của cái kia. Ví dụ:
- Người dùng có quyền truy cập vào các danh mục nhất định không?
- Những sản phẩm nào có chung tag?
- Những mảng nào chứa tất cả các giá trị liệt kê?
Những bài toán này được giải bằng các toán tử so sánh mảng trong PostgreSQL: =, @>, <@ và &&. Mình sẽ đi sâu vào từng toán tử này và phân tích qua ví dụ cụ thể nhé.
= — So sánh mảng bằng nhau
Toán tử này dùng để kiểm tra hai mảng có giống hệt nhau không. Điều kiện trả về TRUE nếu cả hai mảng có cùng độ dài và cùng tập phần tử theo đúng thứ tự.
Ví dụ:
SELECT ARRAY[1, 2, 3] = ARRAY[1, 2, 3] AS are_equal; -- TRUE
SELECT ARRAY[1, 2, 3] = ARRAY[3, 2, 1] AS are_equal; -- FALSE
Lưu ý: Thứ tự phần tử rất quan trọng. Mảng [1, 2, 3] không bằng [3, 2, 1].
@> — Mảng chứa mảng khác
Toán tử này kiểm tra xem một mảng có chứa tất cả phần tử của mảng khác không (không quan trọng thứ tự). Thường dùng khi bạn cần đảm bảo tất cả phần tử cần tìm đều có mặt.
Ví dụ:
SELECT ARRAY[1, 2, 3] @> ARRAY[1, 2] AS contains; -- TRUE
SELECT ARRAY[1, 2, 3] @> ARRAY[4] AS contains; -- FALSE
Tình huống hay gặp: kiểm tra quyền truy cập. Ví dụ, bạn muốn chắc chắn một role nào đó có đủ các quyền cần thiết.
<@ — Mảng là tập con của mảng khác
Ngược lại với toán tử @>. Kiểm tra xem một mảng có nằm hoàn toàn trong mảng khác không.
Ví dụ:
SELECT ARRAY[1, 2] <@ ARRAY[1, 2, 3] AS is_subset; -- TRUE
SELECT ARRAY[4] <@ ARRAY[1, 2, 3] AS is_subset; -- FALSE
Tình huống hay gặp: khi bạn cần kiểm tra một dòng trong bảng có đủ các tag hoặc category cần thiết không.
&& — Giao nhau giữa các mảng
Toán tử này kiểm tra hai mảng có giao nhau không, tức là có ít nhất một phần tử chung.
Ví dụ:
SELECT ARRAY[1, 2, 3] && ARRAY[3, 4, 5] AS intersects; -- TRUE
SELECT ARRAY[1, 2, 3] && ARRAY[6, 7, 8] AS intersects; -- FALSE
Tình huống hay gặp: tìm sản phẩm hoặc bản ghi có chung category hoặc thuộc tính.
Sử dụng toán tử để lọc dữ liệu
Cùng thử áp dụng các toán tử này để lọc dữ liệu trong bảng nhé. Giả sử bạn có bảng products với cột tags là mảng các tag cho từng sản phẩm.
Bảng ví dụ products
| id | name | tags |
|---|---|---|
| 1 | "Product A" | {electronics, sale} |
| 2 | "Product B" | {home, sale} |
| 3 | "Product C" | {electronics, new} |
| 4 | "Product D" | {home, garden} |
Tìm tất cả sản phẩm có tag electronics.
SELECT *
FROM products
WHERE tags @> ARRAY['electronics'];
Kết quả:
| id | name | tags |
|---|---|---|
| 1 | "Product A" | {electronics, sale} |
| 3 | "Product C" | {electronics, new} |
Muốn tìm sản phẩm có tag đúng bằng {home, sale}.
SELECT *
FROM products
WHERE tags = ARRAY['home', 'sale'];
Kết quả:
| id | name | tags |
|---|---|---|
| 2 | "Product B" | {home, sale} |
Giờ thì
tìm sản phẩm có ít nhất một trong các tag {sale, new}.SELECT *
FROM products
WHERE tags && ARRAY['sale', 'new'];
Kết quả:
| id | name | tags |
|---|---|---|
| 1 | "Product A" | {electronics, sale} |
| 2 | "Product B" | {home, sale} |
| 3 | "Product C" | {electronics, new} |
Tìm sản phẩm mà tag chỉ giới hạn đúng {home, garden}.
SELECT *
FROM products
WHERE tags <@ ARRAY['home', 'garden'];
Kết quả:
| id | name | tags |
|---|---|---|
| 4 | "Product D" | {home, garden} |
Ví dụ: kiểm tra nội dung list với CASE
Bạn có thể kết hợp so sánh mảng với biểu thức điều kiện. Ví dụ, tạo query đánh dấu sản phẩm có tag sale là "Giảm giá", còn lại là "Không giảm giá":
SELECT name,
CASE
WHEN tags @> ARRAY['sale'] THEN 'Giảm giá'
ELSE 'Không giảm giá'
END AS discount_status
FROM products;
Kết quả:
| name | discount_status |
|---|---|
| "Product A" | Giảm giá |
| "Product B" | Giảm giá |
| "Product C" | Không giảm giá |
| "Product D" | Không giảm giá |
Lỗi thường gặp và cách tránh
Lỗi: dùng sai thứ tự phần tử với toán tử =. Nhớ là = yêu cầu thứ tự phần tử phải giống hệt. Nếu không quan trọng thứ tự, hãy dùng @> hoặc &&.
Lỗi: không khớp kiểu dữ liệu. Các mảng phải cùng kiểu. Ví dụ, ARRAY['1', '2'] không bằng ARRAY[1, 2] vì một cái là mảng chuỗi, cái kia là mảng số. Luôn kiểm tra kiểu trước khi so sánh.
Lỗi: không có index. Nếu bạn thường xuyên lọc theo mảng, nhớ tạo index (GIN) để tăng hiệu năng.
Những toán tử này giúp bạn xây dựng các truy vấn lọc và so sánh dữ liệu cực mạnh, rất hay gặp trong thực tế: từ phân tích tag sản phẩm đến quản lý quyền truy cập. Dùng chúng hiệu quả sẽ giúp bạn đơn giản hóa các bài toán phức tạp và tối ưu hóa query của mình.
GO TO FULL VERSION