Come ha già menzionato @Milen regexp_matches()
è probabilmente la funzione sbagliata per il tuo scopo. Vuoi una semplice corrispondenza di espressioni regolari (~
)
. In realtà, l'operatore LIKE (~~
)
sarà più veloce :
Presumibilmente il più veloce con 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
Inoltre, vuoi solo mnc.code
di esattamente 3 caratteri.
Con regexp
Potresti scrivi lo stesso con le espressioni regolari ma sarà sicuramente più lento. Ecco un esempio funzionante vicino al tuo originale:
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
Ciò richiede anche msg.src_addr
e msg.dst_addr
essere NOT NULL
.
La seconda query mostra come il controllo aggiuntivo length(mnc.code) = 3
può entrare nel JOIN
condizione o un WHERE
clausola. Stesso effetto qui.
Con regexp_matches()
Potresti fallo funzionare con 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
)
Ma sarà lento in confronto, o almeno così presumo.
Spiegazione:
La tua espressione regexp_matches() restituisce solo un array di tutte le sottostringhe catturate della prima incontro. Poiché catturi solo una sottostringa (una coppia di parentesi nel tuo pattern), otterrai esclusivamente array con un elemento .
Ottieni tutte le corrispondenze con l'opzione "globale" aggiuntiva 'g'
- ma in più righe. Quindi è necessaria una sottoselezione per testarli tutti (o aggregarli). Mettilo in un EXISTS
- semi-unisciti e arrivi a quello che volevi.
Forse puoi riferire con un test delle prestazioni di tutti e tre?Usa EXPLAIN ANALYZE per quello.