PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Correspondência de prefixo mais longa


Eu não saberia de uma função fazendo isso fora da caixa no PostgreSQL.
A CTE recursiva seria o elemento chave para uma solução bastante elegante (disponível no PostgreSQL 8.4 ou posterior).

Estou assumindo uma tabela filter para manter as strings de filtro:
CREATE TABLE filter (f_id int, string text);

E uma tabela tbl para procurar a correspondência mais longa:
CREATE TABLE tbl(t_id int, col text);

Consulta

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;

Detalhado explicação de como o SELECT final funciona nesta resposta relacionada.
Demonstração de trabalho no sqlfiddle.

Você não definiu qual correspondência escolher em um conjunto de correspondências igualmente longas. Estou escolhendo um vencedor arbitrário de empates.

O PostgreSQL 9.1 introduziu CTEs de modificação de dados , então você pode usar isso em um UPDATE declaração diretamente.