sql >> Database teknologi >  >> RDS >> PostgreSQL

Længste præfiksmatch

Jeg kender ikke en funktion, der gør dette ud af boksen i PostgreSQL.
En rekursiv CTE ville være nøgleelementet for en ret elegant løsning (tilgængelig i PostgreSQL 8.4 eller nyere).

Jeg antager et tabel filter for at holde filterstrengene:

CREATE TABLE filter (f_id int, string text);

Og en tabel tbl at søge efter det længste match:

CREATE TABLE tbl(t_id int, col text);

Forespørgsel

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;

Detaljeret forklaring på, hvordan det endelige SELECT fungerer i dette relaterede svar.
Fungerende demo på sqlfiddle.

Du har ikke defineret, hvilken kamp du skal vælge fra et sæt lige lange kampe. Jeg udvælger en vilkårlig vinder fra uafgjort.

PostgreSQL 9.1 introducerede datamodificerende CTE'er , så du kan bruge dette i en UPDATE erklæring direkte.




  1. SQL vs MySQL:Regler om aggregerede operationer og GROUP BY

  2. MYSQL forkert DATETIME-format

  3. Hvad er formålet med at bruge OPTION(MAXDOP 1) i SQL Server?

  4. SQL Server Service Broker