Ký tự đại diện PostgreSQL THÍCH cho bất kỳ danh sách các từ


156

Tôi có một danh sách đơn giản ~ 25 từ. Tôi có một trường varchar trong PostgreSQL, giả sử danh sách đó là ['foo', 'bar', 'baz']. Tôi muốn tìm bất kỳ hàng nào trong bảng có bất kỳ từ nào trong số đó. Điều này sẽ làm việc, nhưng tôi muốn một cái gì đó thanh lịch hơn.

select *
from table
where (lower(value) like '%foo%' or lower(value) like '%bar%' or lower(value) like '%baz%')

Câu trả lời:


165

Bạn có thể sử dụng SIMILAR TOtoán tử Postgres ' hỗ trợ thay thế, tức là

select * from table where lower(value) similar to '%(foo|bar|baz)%';

1
Regex có thể tăng tốc độ này lên một chút: dba.stackexchange.com/questions/10694/iêu
Xấp xỉ

Sao bạn biết được ? hầu hết các tài liệu tôi đã đọc đều nói rằng regex chậm hơn và %% ...
DestyNova 24/07/2015

5
Theo dba.stackexchange.com/a/10696/27757 SIMILAR TO được dịch nội bộ sang tìm kiếm regex
Mark K Cowan

Tôi nghĩ rằng việc sử dụng lower()là không hiệu quả vì trước tiên nó sẽ chuyển đổi từng chuỗi thành chữ thường, sẽ tốn kém hơn so với chỉ một trường hợp không phân biệt chữ hoa chữ thường
gilad mayani

228

PostgreSQL cũng hỗ trợ các biểu thức chính quy POSIX đầy đủ :

select * from table where value ~* 'foo|bar|baz';

Đây ~*là một trường hợp không nhạy cảm, ~là trường hợp nhạy cảm.

Một tùy chọn khác là sử dụng BẤT K ::

select * from table where value  like any (array['%foo%', '%bar%', '%baz%']);
select * from table where value ilike any (array['%foo%', '%bar%', '%baz%']);

Bạn có thể sử dụng BẤT K with với bất kỳ toán tử nào mang lại giá trị boolean. Tôi nghi ngờ rằng các tùy chọn regex sẽ nhanh hơn nhưng BẤT K is là một công cụ hữu ích cần có trong hộp công cụ của bạn.


Thật thú vị, trong khi cả hai phương pháp này đều thanh lịch hơn giải pháp của @chmullig (nên +1), khi kiểm tra ít nhất 3 tùy chọn, chúng thực hiện chậm hơn đáng kể trên các bảng lớn (91,5 triệu bản ghi trong trường hợp của tôi). Tôi đã thấy thời gian tăng khoảng 2 lần khi sử dụng một trong hai. Bất cứ ý tưởng tại sao đó có thể là?
sage88

@ sage88 Tôi không biết trên đỉnh đầu của mình nhưng Erwin Brandstetter có thể và thêm các chỉ số trigram có thể giúp ích.
mu quá ngắn

13

Trên thực tế, có một toán tử cho điều đó trong PostgreSQL:

SELECT *
FROM table
WHERE lower(value) ~~ ANY('{%foo%,%bar%,%baz%}');


Vì vậy, ilike có thể được sử dụng với bất kỳ & mảng theo cùng một cách? Điều này có vẻ sạch sẽ nếu không có nhu cầu cho regex ưa thích. Hoặc nó sẽ được dịch sang regex trong nội bộ?
mlt

@mlt Đó là một câu hỏi hay, đọc tài liệu không cung cấp câu trả lời rõ ràng. SIMILAR TOkhông chuyển đổi thành Biểu thức chính quy, ~toán tử là viết tắt của POSIX Biểu thức chính quy, nhưng điều này không rõ ràng LIKE.
jlandercy

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.