PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie man Tabellen mit Regex verbindet

Wie @Milen bereits erwähnt hat regexp_matches() ist wahrscheinlich die falsche Funktion für Ihren Zweck. Sie möchten eine einfache Übereinstimmung mit regulären Ausdrücken (~ ) . Eigentlich ist der LIKE-Operator (~~ ) wird schneller :

Vermutlich am schnellsten mit 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

Außerdem wollen Sie nur mnc.code aus genau 3 Zeichen.

Mit regulärem Ausdruck

Sie könnten Schreiben Sie dasselbe mit regulären Ausdrücken, aber es wird definitiv langsamer sein. Hier ist ein funktionierendes Beispiel, das Ihrem Original nahe kommt:

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

Dies erfordert auch msg.src_addr und msg.dst_addr NOT NULL sein .

Die zweite Abfrage demonstriert, wie die zusätzliche Prüfung length(mnc.code) = 3 können in den JOIN gehen Bedingung oder ein WHERE Klausel. Gleicher Effekt hier.

Mit regexp_matches()

Sie könnten damit das funktioniert mit 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
    )

Aber es wird im Vergleich langsam sein - oder so gehe ich davon aus.

Erklärung:
Ihr regexp_matches()-Ausdruck gibt nur ein Array aller erfassten Teilstrings des ersten zurück passen. Da Sie nur einen Teilstring (ein Klammerpaar in Ihrem Muster) erfassen, erhalten Sie ausschließlich Arrays mit einem Element .

Sie erhalten alle Übereinstimmungen mit dem zusätzlichen "global"-Schalter 'g' - aber in mehreren Reihen. Sie benötigen also eine Unterauswahl, um sie alle zu testen (oder zu aggregieren). Setzen Sie das in ein EXISTS - Semi-Join und Sie kommen zu dem, was Sie wollten.

Vielleicht können Sie sich mit einem Leistungstest zurückmelden von allen drei? Verwenden Sie EXPLAIN ANALYZE dafür.