sql >> Databasteknik >  >> RDS >> PostgreSQL

Längsta prefixmatchning

Jag skulle inte känna till en funktion som gör detta direkt i PostgreSQL.
En rekursiv CTE skulle vara nyckelelementet för en ganska elegant lösning (tillgänglig i PostgreSQL 8.4 eller senare).

Jag antar ett tabell filter för att hålla filtersträngarna:

CREATE TABLE filter (f_id int, string text);

Och en tabell tbl för att söka efter den längsta matchningen:

CREATE TABLE tbl(t_id int, col text);

Fråga

WITH RECURSIVE
     f AS (SELECT f_id, string, length(string) AS flen FROM filter)
    ,t AS (SELECT t_id, col, length(col) AS tlen FROM tbl)
    ,x AS (
    SELECT t.t_id, f.f_id, t.col, f.string
          ,2 AS match, LEAST(flen, tlen) AS len
    FROM   t
    JOIN   f ON left(t.col, 1) = left(f.string, 1)

    UNION ALL
    SELECT t_id, f_id, col, string, match + 1, len
    FROM   x
    WHERE  left(col, match) = left(string, match)
    AND    match <= len
    )
SELECT DISTINCT
       f_id
      ,string
      ,first_value(col) OVER w AS col
      ,first_value(t_id) OVER w AS t_id
      ,(first_value(match) OVER w -1) AS longest_match
FROM   x
WINDOW w AS (PARTITION BY f_id ORDER BY match DESC)
ORDER  BY 2,1,3,4;

Detaljerad förklaring hur den slutliga SELECT fungerar i detta relaterade svar.
Fungerande demo på sqlfiddle.

Du har inte definierat vilken match du ska välja från en uppsättning lika långa matcher. Jag väljer en godtycklig vinnare från oavgjort.

PostgreSQL 9.1 introducerade datamodifierande CTE:er , så du kan använda detta i en UPDATE uttalande direkt.




  1. REGEXP_SUBSTR() Funktion i Oracle

  2. Infoga data i Oracle-databasen med php

  3. SQL Server 2016:Skapa en databas

  4. Exportera data från en MySQL-databas