sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL, trigramy a podobnosti

Koncept podobnosti trigramů se opírá o to, že každá věta je rozdělena na „trigramy“ (sekvence tří po sobě jdoucích písmen) a výsledek se považuje za SET (tj. na pořadí nezáleží a nemáte opakované hodnoty). Před zvážením věty jsou přidány dvě mezery na začátek a jedna na konec a jednoduché mezery jsou nahrazeny dvojitými.

Trigramy jsou speciálním případem N-gramů .

Sada trigramů odpovídající „Chateau blanc“ se najde nalezením všech sekvencí tří písmen, která se na ní objevují:

  chateau  blanc
---                 => '  c'
 ---                => ' ch'
  ---               => 'cha'
   ---              => 'hat'
    ---             => 'ate'
     ---            => 'tea'
      ---           => 'eau'
       ---          => 'au '
        ---         => 'u  '
         ---        => '  b'
          ---       => ' bl'
           ---      => 'bla'
            ---     => 'lan'
             ---    => 'anc'
              ---   => 'nc '

Když je seřadíte a vyjmete opakování, získáte:

'  b'
'  c'
' bl'
' ch'
'anc'
'ate'
'au '
'bla'
'cha'
'eau'
'hat'
'lan'
'nc '
'tea'

To může PostgreSQL vypočítat pomocí funkce show_trgm :

SELECT show_trgm('Chateau blanc') AS A

A = [  b,  c, bl, ch,anc,ate,au ,bla,cha,eau,hat,lan,nc ,tea]

... který má 14 trigramů. (Zkontrolujte pg_trgm ).

A sada trigramů odpovídající "Chateau Cheval Blanc" je:

SELECT show_trgm('Chateau Cheval Blanc') AS B 

B = [  b,  c, bl, ch,anc,ate,au ,bla,cha,che,eau,evl,hat,hev,la ,lan,nc ,tea,vla]

... který má 19 trigramů

Pokud spočítáte, kolik trigramů má obě sady společné, zjistíte, že mají následující:

A intersect B = 
    [  b,  c, bl, ch,anc,ate,au ,bla,cha,eau,hat,lan,nc ,tea]

a ty, které mají celkem, jsou:

A union B = 
    [  b,  c, bl, ch,anc,ate,au ,bla,cha,che,eau,evl,hat,hev,la ,lan,nc ,tea,vla]

To znamená, že obě věty mají společných 14 trigramů a celkem 19.
Podobnost se vypočítá takto:

 similarity = 14 / 19

Můžete to zkontrolovat pomocí:

SELECT 
    cast(14.0/19.0 as real) AS computed_result, 
    similarity('Chateau blanc', 'chateau cheval blanc') AS function_in_pg

a uvidíte, že dostanete:0.736842

... což vysvětluje jak podobnost se vypočítává a proč získáte hodnoty, které získáte.

POZNÁMKA:Průsečík a sjednocení můžete vypočítat pomocí:

SELECT 
   array_agg(t) AS in_common
FROM
(
    SELECT unnest(show_trgm('Chateau blanc')) AS t 
    INTERSECT 
    SELECT unnest(show_trgm('chateau chevla blanc')) AS t
    ORDER BY t
) AS trigrams_in_common ;

SELECT 
   array_agg(t) AS in_total
FROM
(
    SELECT unnest(show_trgm('Chateau blanc')) AS t 
    UNION 
    SELECT unnest(show_trgm('chateau chevla blanc')) AS t
) AS trigrams_in_total ;

A toto je způsob, jak prozkoumat podobnost různých párů vět:

WITH p AS
(
    SELECT 
      'This is just a sentence I''ve invented'::text AS f1,
      'This is just a sentence I''ve also invented'::text AS f2
),
t1 AS
(
    SELECT unnest(show_trgm(f1)) FROM p
),
t2 AS
(
    SELECT unnest(show_trgm(f2)) FROM p
),
x AS
(
    SELECT
        (SELECT count(*) FROM 
            (SELECT * FROM t1 INTERSECT SELECT * FROM t2) AS s0)::integer AS same,
        (SELECT count(*) FROM 
            (SELECT * FROM t1 UNION     SELECT * FROM t2) AS s0)::integer AS total,
        similarity(f1, f2) AS sim_2
FROM
    p 
)
SELECT
    same, total, same::real/total::real AS sim_1, sim_2
FROM
    x ;

Můžete si to ověřit na Rextester



  1. T-SQL rozdělený řetězec

  2. Jak mohu použít PDO k načtení pole výsledků v PHP?

  3. Ekvivalent GROUP_CONCAT v Django

  4. Jak echo out řádky tabulky z db (php)