PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment joindre des tables sur regex

Comme @Milen l'a déjà mentionné regexp_matches() est probablement la mauvaise fonction pour votre objectif. Vous voulez une simple correspondance d'expression régulière (~ ) . En fait, l'opérateur LIKE (~~ ) sera plus rapide :

Vraisemblablement le plus rapide avec 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

De plus, vous ne voulez que mnc.code d'exactement 3 caractères.

Avec regexp

Vous pourriez écrivez la même chose avec des expressions régulières mais ce sera certainement plus lent. Voici un exemple de travail proche de votre 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

Cela nécessite également msg.src_addr et msg.dst_addr être NOT NULL .

La deuxième requête montre comment la vérification supplémentaire length(mnc.code) = 3 peut aller dans le JOIN condition ou un WHERE clause. Même effet ici.

Avec regexp_matches()

Vous pourriez faire fonctionner cela avec 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
    )

Mais ce sera lent en comparaison - du moins je suppose.

Explication :
Votre expression regexp_matches() renvoie simplement un tableau de toutes les sous-chaînes capturées de la première match. Comme vous ne capturez qu'une seule sous-chaîne (une paire de crochets dans votre modèle), vous obtiendrez exclusivement des tableaux avec un élément .

Vous obtenez toutes les correspondances avec le commutateur "globalement" supplémentaire 'g' - mais en plusieurs rangées. Vous avez donc besoin d'une sous-sélection pour les tester tous (ou les agréger). Mettez cela dans un EXISTS - semi-joindre et vous arrivez à ce que vous vouliez.

Peut-être pouvez-vous faire un rapport avec un test de performance des trois ? Utilisez EXPLAIN ANALYZE pour ça.