Както @Milen вече спомена regexp_matches()
вероятно е грешната функция за вашата цел. Искате просто съвпадение на регулярен израз (~код> )
. Всъщност операторът LIKE (~~
)
ще бъдепо-бързо :
Привидно най-бързо с 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
Освен това искате само mnc.code
от точно 3 знака.
С регулярен израз
Вие можете напишете същото с регулярни изрази, но със сигурност ще бъде по-бавно. Ето работещ пример, близък до вашия оригинал:
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
Това също изисква msg.src_addr
и msg.dst_addr
да бъде NOT NULL
.
Втората заявка демонстрира как допълнителната проверка length(mnc.code) =3
може да влезе в JOIN
условие или WHERE
клауза. Същият ефект тук.
С regexp_matches()
Вие можете направете това да работи с 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
)
Но ще бъде бавно в сравнение - или поне така предполагам.
Обяснение:
Вашият израз regexp_matches() просто връща масив от всички уловени поднизове на първия съвпада. Тъй като улавяте само един подниз (една двойка скоби във вашия шаблон), ще получите изключително масиви с един елемент .
Получавате всички съвпадения с допълнителния превключвател "глобално" 'g'
- но в няколко реда. Така че имате нужда от подизбор, за да ги тествате всички (или обобщени). Поставете това в EXISTS
- полусъединяване и ще стигнете до това, което сте искали.
Може би можете да докладвате с тест за ефективност от трите? Използвайте EXPLAIN ANALYZE за това.