Mảng thường được dùng để lưu nhiều giá trị trong một cột — ví dụ như tag, số điện thoại, vai trò hoặc sở thích. Nhưng làm sao để biết trong mảng có giá trị mình cần không, hoặc ngược lại — tất cả phần tử có thỏa mãn điều kiện nào đó không? PostgreSQL cung cấp mấy công cụ tiện cho việc này: ANY, ALL và array_contains(). Cùng xem từng cái một nhé.
ANY là gì?
Giả sử bạn có một mảng chứa nhiều giá trị, ví dụ ID sản phẩm, số điện thoại hoặc danh sách sở thích. Thường sẽ có lúc bạn cần kiểm tra xem trong mảng có giá trị cụ thể nào đó không. Lúc này, toán tử ANY sẽ phát huy tác dụng. Nó giúp kiểm tra xem "đối tượng cần tìm" của mình có nằm trong mảng không.
Cú pháp ANY
SELECT *
FROM your_table
WHERE value = ANY(array_column);
Ở đây:
array_column— là mảng mà mình kiểm tra.value— là giá trị mình muốn tìm trong mảng.
Ví dụ dùng ANY
Giả sử có bảng students với cấu trúc như sau:
| id | name | hobbies |
|---|---|---|
| 1 | Otto | {doc sach, boi loi, co vua} |
| 2 | Eva | {am nhac, doc sach, the thao} |
| 3 | Alex | {ve, am nhac} |
| 4 | Maria | {co vua, bong da} |
Bạn muốn tìm sinh viên nào có sở thích là bơi lội. Truy vấn sẽ như sau:
SELECT *
FROM students
WHERE 'boi loi' = ANY(hobbies);
Kết quả:
| id | name | hobbies |
|---|---|---|
| 1 | Otto | {doc sach, boi loi, co vua} |
Nói ngắn gọn, ANY kiểm tra: "Trong mảng này có giá trị này không?".
Tin nhưng phải kiểm hết! Dùng ALL
Bây giờ tưởng tượng ngược lại: bạn cần chắc chắn tất cả phần tử trong mảng đều thỏa mãn một quy tắc nào đó. PostgreSQL có toán tử ALL cho việc này. Nó giúp kiểm tra xem tất cả phần tử trong mảng có thỏa mãn điều kiện, ví dụ như lớn hơn một số nào đó, hoặc bằng một giá trị nào đó, hoặc bất kỳ điều kiện logic nào khác.
Cú pháp ALL
SELECT *
FROM your_table
WHERE value < ALL(array_column);
Ở đây:
array_column— là mảng mình kiểm tra.value < ALL(...)nghĩa là tất cả phần tử trong mảng phải lớn hơn giá trị này.
Quay lại bảng students. Giả sử bạn muốn tìm sinh viên mà tất cả sở thích đều bắt đầu bằng chữ "doc sach". Truy vấn:
SELECT *
FROM students
WHERE 'doc sach' = ALL(hobbies);
Kết quả sẽ rỗng, vì không ai có tất cả sở thích đều là "doc sach". Để ví dụ dễ hiểu hơn (và chạy được), thử nghĩ về dữ liệu số nhé.
Giả sử có bảng orders:
| id | customer | prices |
|---|---|---|
| 1 | Otto | {100, 200, 300} |
| 2 | Eva | {50, 60, 70} |
| 3 | Alex | {500, 600, 700} |
Tìm tất cả đơn hàng mà mỗi giá đều nhỏ hơn 400:
SELECT *
FROM orders
WHERE 400 > ALL(prices);
Kết quả:
| id | customer | prices |
|---|---|---|
| 1 | Otto | {100, 200, 300} |
| 2 | Eva | {50, 60, 70} |
Lọc dòng theo nội dung mảng
Mình đã xem qua các hàm và toán tử cơ bản để tìm kiếm dữ liệu trong mảng, nhưng thực tế dùng như nào? Xem vài ví dụ nhé.
Ví dụ 1: Tìm sinh viên có ít nhất một sở thích là âm nhạc
Bảng gốc:
| id | name | hobbies |
|---|---|---|
| 1 | Otto | {doc sach, am nhac, chay} |
| 2 | Eva | {ve, boi loi} |
| 3 | Maria | {am nhac, boxing} |
| 4 | Alex | {bong da, boxing, choi ban} |
SELECT *
FROM students
WHERE 'am nhac' = ANY(hobbies);
Kết quả:
| id | name | hobbies |
|---|---|---|
| 1 | Otto | {doc sach, am nhac, chay} |
| 3 | Maria | {am nhac, boxing} |
Ví dụ 2: Tìm đơn hàng mà tất cả giá đều lớn hơn 100
Bảng orders gốc:
| id | customer | prices |
|---|---|---|
| 1 | Otto | {150, 200, 300} |
| 2 | Eva | {50, 120, 130} |
| 3 | Maria | {200, 250, 100} |
| 4 | Alex | {110, 115, 120} |
SELECT *
FROM orders
WHERE 100 < ALL(prices);
Kết quả:
| id | customer | prices |
|---|---|---|
| 1 | Otto | {150, 200, 300} |
| 4 | Alex | {110, 115, 120} |
Lỗi thường gặp và cách tránh
Khi làm việc với mảng, nhất là khi tìm kiếm dữ liệu, có vài "bẫy" dễ dính lắm nha.
Lỗi: Dùng sai ANY hoặc ALL. Ví dụ, nếu bạn nhầm lẫn giữa các toán tử, kết quả sẽ rất bất ngờ.
-- Sai:
SELECT *
FROM students
WHERE hobbies = ANY('doc sach');
Ở ví dụ này, lỗi là hobbies là mảng, còn 'doc sach' là chuỗi. Chính mảng mới nên kiểm tra với ANY, không phải ngược lại.
Lỗi: Chỉ số mảng bắt đầu từ 1 chứ không phải 0. Nếu bạn dùng mảng trong các hàm khác hoặc lấy phần tử thủ công, nhớ đặc điểm này của PostgreSQL nhé.
Lỗi: Không tạo index cho mảng. Nếu bạn thường xuyên tìm kiếm trên mảng (ANY, ALL), tạo index sẽ giúp truy vấn nhanh hơn nhiều.
GO TO FULL VERSION