Seperti yang sudah disebutkan @Milen regexp_matches()
mungkin fungsi yang salah untuk tujuan Anda. Anda menginginkan pencocokan ekspresi reguler (~
)
. Sebenarnya, LIKE operator (~~
)
akan lebih cepat :
Mungkin tercepat dengan LIKE
SELECT msg.message
,msg.src_addr
,msg.dst_addr
,mnc.name
FROM mnc
JOIN msg ON msg.src_addr ~~ ('%38' || mnc.code || '%')
OR msg.dst_addr ~~ ('%38' || mnc.code || '%')
WHERE length(mnc.code) = 3
Selain itu, Anda hanya ingin mnc.code
tepat 3 karakter.
Dengan regexp
Anda bisa tulis yang sama dengan ekspresi reguler tetapi pasti akan lebih lambat. Berikut adalah contoh kerja yang mirip dengan aslinya:
SELECT msg.message
,msg.src_addr
,msg.dst_addr
,mnc.name
FROM mnc
JOIN msg ON (msg.src_addr || '+' || msg.dst_addr) ~ (38 || mnc.code)
AND length(mnc.code) = 3
Ini juga memerlukan msg.src_addr
dan msg.dst_addr
menjadi NOT NULL
.
Kueri kedua menunjukkan bagaimana pemeriksaan tambahan length(mnc.code) = 3
bisa masuk ke JOIN
kondisi atau WHERE
ayat. Efek yang sama di sini.
Dengan regexp_matches()
Anda bisa buat ini berfungsi dengan regexp_matches()
:
SELECT msg.message
,msg.src_addr
,msg.dst_addr
,mnc.name
FROM mnc
JOIN msg ON EXISTS (
SELECT *
FROM regexp_matches(msg.src_addr ||'+'|| msg.dst_addr, '38(...)', 'g') x(y)
WHERE y[1] = mnc.code
)
Tapi itu akan lambat dibandingkan - atau begitulah menurut saya.
Penjelasan:
Ekspresi regexp_matches() Anda baru saja mengembalikan larik dari semua substring yang diambil dari pertama cocok. Karena Anda hanya menangkap satu substring (sepasang tanda kurung dalam pola Anda), Anda akan secara eksklusif mendapatkan array dengan satu elemen .
Anda mendapatkan semua kecocokan dengan sakelar "global" tambahan 'g'
- tetapi dalam beberapa baris. Jadi, Anda memerlukan sub-pilih untuk menguji semuanya (atau agregat). Masukkan itu ke dalam EXISTS
- semi-bergabung dan Anda sampai pada apa yang Anda inginkan.
Mungkin Anda dapat melaporkan kembali dengan pengujian kinerja dari ketiganya? Gunakan MENJELASKAN ANALISIS untuk itu.