Como @Milen já mencionou
regexp_matches()
é provavelmente a função errada para o seu propósito. Você quer uma simples correspondência de expressão regular (~
)
. Na verdade, o operador LIKE (~~
)
será mais rápido :Presumivelmente mais rápido com 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
Além disso, você deseja apenas
mnc.code
de exatamente 3 caracteres. Com regexp
Você poderia escreva o mesmo com expressões regulares, mas com certeza será mais lento. Aqui está um exemplo de trabalho próximo ao seu 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
Isso também requer
msg.src_addr
e msg.dst_addr
ser NOT NULL
. A segunda consulta demonstra como a verificação adicional
length(mnc.code) = 3
pode entrar no JOIN
condição ou um WHERE
cláusula. Mesmo efeito aqui. Com regexp_matches()
Você poderia faça isso funcionar com
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
)
Mas será lento em comparação - ou assim eu suponho.
Explicação:
Sua expressão regexp_matches() apenas retorna uma matriz de todas as substrings capturadas da primeira Combine. Como você captura apenas uma substring (um par de colchetes em seu padrão), você obterá exclusivamente arrays com um elemento .
Você obtém todas as correspondências com a opção "globalmente" adicional
'g'
- mas em várias linhas. Então você precisa de uma sub-seleção para testar todos eles (ou agregar). Coloque isso em um EXISTS
- semi-junte e você chega ao que queria. Talvez você possa relatar com um teste de desempenho de todos os três? Use EXPLAIN ANALYZE por isso.