Som @Milen redan nämnt regexp_matches()
är förmodligen fel funktion för ditt syfte. Du vill ha en enkel matchning med reguljära uttryck (~
)
. Faktiskt är LIKE-operatorn (~~
)
blir snabbare :
Förmodligen snabbast med 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
Dessutom vill du bara ha mnc.code
med exakt 3 tecken.
Med regexp
Du kunde skriv samma sak med reguljära uttryck men det kommer definitivt att gå långsammare. Här är ett fungerande exempel nära ditt original:
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
Detta kräver också msg.src_addr
och msg.dst_addr
vara NOT NULL
.
Den andra frågan visar hur den extra kontrollen length(mnc.code) = 3
kan gå in i JOIN
villkor eller en WHERE
klausul. Samma effekt här.
Med regexp_matches()
Du kunde få detta att fungera med 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
)
Men det kommer att gå långsamt i jämförelse - eller så antar jag.
Förklaring:
Ditt regexp_matches()-uttryck returnerar bara en array av alla infångade delsträngar av den första match. Eftersom du bara fångar en delsträng (ett par parenteser i ditt mönster) får du exklusivt arrayer med ett element .
Du får alla matchningar med den extra "globalt" omkopplaren 'g'
- men i flera rader. Så du behöver ett underval för att testa dem alla (eller sammanställa). Lägg det i en EXISTS
- semi-join och du kommer fram till vad du ville.
Kanske kan du rapportera tillbaka med ett prestationstest av alla tre? Använd EXPLAIN ANALYZE för det.