Jak już wspomniał @Milen regexp_matches()
jest prawdopodobnie niewłaściwą funkcją dla twojego celu. Potrzebujesz prostego regularnego dopasowania wyrażenia (~
)
. W rzeczywistości operator LIKE (~~
)
będzie szybciej :
Prawdopodobnie najszybszy dzięki 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
Ponadto potrzebujesz tylko mnc.code
dokładnie 3 znaki.
Z wyrażeniem regularnym
możesz napisz to samo z wyrażeniami regularnymi, ale z pewnością będzie to wolniejsze. Oto działający przykład zbliżony do oryginału:
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
Wymaga to również msg.src_addr
i msg.dst_addr
być NOT NULL
.
Drugie zapytanie pokazuje, jak dodatkowe sprawdzenie length(mnc.code) = 3
można przejść do JOIN
warunek lub WHERE
klauzula. Ten sam efekt tutaj.
Z regexp_matches()
możesz spraw, aby to działało z 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
)
Ale w porównaniu będzie to powolne - a przynajmniej tak zakładam.
Wyjaśnienie:
Twoje wyrażenie regexp_matches() po prostu zwraca tablicę wszystkich przechwyconych podciągów pierwszego mecz. Ponieważ przechwycisz tylko jeden podciąg (jedną parę nawiasów we wzorcu), otrzymasz wyłącznie tablice z jednym elementem .
Otrzymujesz wszystkie dopasowania z dodatkowym przełącznikiem „globalnie” 'g'
- ale w wielu rzędach. Potrzebujesz więc podselekcji, aby przetestować je wszystkie (lub zagregować). Umieść to w EXISTS
- pół-dołącz i osiągniesz to, czego chciałeś.
Może możesz zgłosić się z testem wydajności wszystkich trzech? Użyj WYJAŚNIJ ANALIZĘ za to.