Como @Milen ya mencionó regexp_matches()
es probablemente la función incorrecta para su propósito. Desea una simple coincidencia de expresiones regulares (~
)
. En realidad, el operador LIKE (~~
)
será más rápido :
Presumiblemente más rápido 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
Además, solo desea mnc.code
de exactamente 3 caracteres.
Con expresión regular
podrías escriba lo mismo con expresiones regulares, pero definitivamente será más lento. Aquí hay un ejemplo de trabajo cercano a su 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
Esto también requiere msg.src_addr
y msg.dst_addr
ser NOT NULL
.
La segunda consulta demuestra cómo la comprobación adicional length(mnc.code) = 3
puede ir a JOIN
condición o un WHERE
cláusula. Mismo efecto aquí.
Con regexp_matches()
podrías haz que esto funcione 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
)
Pero será lento en comparación, o eso supongo.
Explicación:
Su expresión regexp_matches() solo devuelve una matriz de todas las subcadenas capturadas de la primera juego. Como solo captura una subcadena (un par de corchetes en su patrón), obtendrá exclusivamente matrices con un elemento .
Obtienes todas las coincidencias con el interruptor adicional "globalmente" 'g'
- pero en varias filas. Por lo tanto, necesita una subselección para probarlos todos (o agregados). Pon eso en un EXISTS
- semi-unir y llegas a lo que querías.
Tal vez pueda informar con una prueba de rendimiento de los tres? Use EXPLAIN ANALYZE por eso.