Как уже упоминалось @Milen regexp_matches()
, вероятно, не та функция, которая вам нужна.Вы хотите простое совпадение регулярного выражения (~
) .На самом деле, оператор LIKE (~~
) будет быстрее :
Предположительно быстрее всего с 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
Кроме того, вы толькохотите mnc.code
точно из 3 символов.
С помощью regexp
Вы могли бы написать то же самое с регулярными выражениями, но это, безусловно, будет медленнее.Вот рабочий пример, близкий к вашему оригиналу:
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
Для этого также необходимо, чтобы msg.src_addr
и msg.dst_addr
были NOT NULL
.
Второй запрос демонстрирует, как дополнительная проверка length(mnc.code) = 3
может перейти в условие JOIN
или предложение WHERE
.Тот же эффект здесь.
С regexp_matches ()
Вы могли бы сделать эту работу с 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
)
Но это будет медленное сравнение - или я так полагаю.
Объяснение:
Ваше выражение regexp_matches () просто возвращает массив всех захваченных подстрок первый матч.Поскольку вы захватываете только одну подстроку (одну пару скобок в шаблоне), вы получите исключительно массивы с одним элементом .
Вы получите все совпадения с дополнительнымипереключатель «глобально» 'g'
- но в несколько рядов.Таким образом, вам нужен дополнительный выбор, чтобы проверить их все (или совокупность).Поместите это в EXISTS
- полусоединение, и вы получите то, что хотели.
Может быть, вы можете сообщить о результатах теста из всех трех?Для этого используйте EXPLAIN ANALYZE .