Jak již @Milen zmínil regexp_matches()
je pravděpodobně špatná funkce pro váš účel. Chcete jednoduchou shodu s regulárním výrazem (~
)
. Ve skutečnosti operátor LIKE (~~
)
bude rychlejší :
Pravděpodobně nejrychlejší s 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
Kromě toho chcete pouze mnc.code
přesně 3 znaků.
S regulárním výrazem
Mohli byste napsat to samé s regulárními výrazy, ale bude to určitě pomalejší. Zde je funkční příklad blízký vašemu originálu:
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
To také vyžaduje msg.src_addr
a msg.dst_addr
být NOT NULL
.
Druhý dotaz ukazuje, jak další kontrola length(mnc.code) = 3
můžete přejít do JOIN
podmínku nebo WHERE
doložka. Stejný efekt zde.
Pomocí regexp_matches()
Mohli byste aby to fungovalo pomocí 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
)
Ale ve srovnání to bude pomalé - alespoň to předpokládám.
Vysvětlení:
Váš výraz regexp_matches() pouze vrací pole všech zachycených podřetězců prvního zápas. Protože zachytíte pouze jeden podřetězec (jeden pár závorek ve vzoru), získáte výhradně pole s jedním prvkem .
Získáte všechny shody pomocí dalšího „globálně“ přepínače 'g'
- ale ve více řadách. Takže potřebujete podvýběr, abyste je všechny otestovali (nebo agregovali). Vložte to do EXISTS
- semi-join a dosáhnete toho, co jste chtěli.
Možná se můžete vrátit pomocí testu výkonu ze všech tří? Použijte EXPLAIN ANALYZE za to.