Wildcard PostgreSQL SEPERTI untuk setiap daftar kata


156

Saya punya daftar sederhana ~ 25 kata. Saya memiliki bidang varchar di PostgreSQL, katakanlah daftar itu ['foo', 'bar', 'baz']. Saya ingin menemukan baris di meja saya yang memiliki kata-kata itu. Ini akan berhasil, tetapi saya ingin sesuatu yang lebih elegan.

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

Jawaban:


166

Anda dapat menggunakan SIMILAR TOoperator Postgres yang mendukung pergantian, yaitu

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

1
Regex mungkin mempercepat ini sedikit: dba.stackexchange.com/questions/10694/…
kira

Bagaimana kamu bisa tahu ? sebagian besar dokumentasi yang saya baca mengatakan bahwa regex lebih lambat dan LIKE% ...
DestyNova

5
Menurut dba.stackexchange.com/a/10696/27757 SIMILAR TO diterjemahkan secara internal ke pencarian regex
Mark K Cowan

Saya pikir menggunakan lower()tidak efektif karena pertama-tama akan mengkonversi setiap string menjadi huruf kecil, yang lebih mahal daripada hanya pertandingan dengan huruf besar-kecil
gilad mayani

229

PostgreSQL juga mendukung ekspresi reguler POSIX lengkap :

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

Ini ~*untuk pertandingan yang tidak peka huruf besar kecil, ~peka huruf besar kecil.

Pilihan lain adalah menggunakan APA PUN :

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

Anda dapat menggunakan APA SAJA dengan operator apa pun yang menghasilkan boolean. Saya menduga bahwa opsi regex akan lebih cepat tetapi APAPUN adalah alat yang berguna untuk ada di kotak peralatan Anda.


Menariknya, walaupun kedua metode ini lebih elegan daripada solusi @chmullig (jadi +1), ketika memeriksa 3 opsi setidaknya, mereka mengeksekusi lebih lambat secara signifikan pada tabel besar (91,5 juta catatan dalam kasus saya). Saya melihat peningkatan waktu sekitar 2x ketika menggunakan salah satu dari ini. Adakah yang tahu mengapa itu terjadi?
sage88

@ sage88 Saya tidak tahu dari atas kepala saya tetapi Erwin Brandstetter mungkin dan menambahkan indeks trigram mungkin membantu.
mu terlalu pendek

13

Sebenarnya ada operator untuk itu di PostgreSQL:

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


Jadi bisa ilike digunakan dengan setiap & array dalam cara yang sama? Ini terlihat bersih jika tidak perlu untuk regex mewah. Atau apakah itu akan diterjemahkan menjadi regex secara internal?
mlt

@mlt Itu pertanyaan yang bagus, membaca dokumen tidak memberikan jawaban eksplisit. SIMILAR TOdikonversi menjadi Ekspresi Reguler, ~operator adalah singkatan dari Ekspresi Reguler POSIX, tetapi ini tidak jelas untuk LIKE.
jlandercy

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.