CodeGym /Các khóa học /SQL SELF /So sánh và lọc mảng: =, @>, <@, &&

So sánh và lọc mảng: =, @>, <@, &&

SQL SELF
Mức độ , Bài học
Có sẵn

Đô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: =, @>, <@&&. 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.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION