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.