2017-07-05 1 views
0

Plate-forme: PostgreSQLREJOIGNEZ le dossier avec le nom le plus semblable à chaque rangée de plusieurs tables

Tables:

shortlist: name (text), city (text)... 
data1:  name (text), ranking (integer), score1 (double)... 
data2:  name (text), ranking (integer), score1 (double)... 
data3:  name (text), ranking (integer), score1 (double)... 
data4:  name (text), ranking (integer), score1 (double)... 

Il y a un nombre limité de tableaux de données de format similaire.


Je voudrais me joindre à chaque ligne shortlist avec la ligne dans chaque tableau data qui a le nom le plus semblable déterminé par similarity(shortlist.name, data#.name).


Pseudo code de la même idée:

for each s_row in shortlist: 
    select shortlist.* 
    join (SELECT data1.*, similarity(s_row.name, data1.name) AS sim FROM data1 ORDER BY sim DESC LIMIT 1) 
    join (SELECT data2.*, similarity(s_row.name, data2.name) AS sim FROM data2 ORDER BY sim DESC LIMIT 1) 
    join (SELECT data3.*, similarity(s_row.name, data3.name) AS sim FROM data3 ORDER BY sim DESC LIMIT 1) 
    join (SELECT data4.*, similarity(s_row.name, data4.name) AS sim FROM data4 ORDER BY sim DESC LIMIT 1) 

Est-il possible de le faire dans SQL?

+1

Un enregistrement donné dans l'ensemble de résultats pourrait inclure des bits et des pièces provenant des quatre tables. Cela ressemble à une mauvaise conception de base de données pour moi. –

+0

Que faire si la similarité dans data1 est inférieure à celle de data2? Quel nom voulez-vous voir? Ou voulez-vous toujours voir toutes les lignes des tables "données"? qui sont "similaires" à celui de la liste des présélection? –

+0

@a_horse_with_no_name Ce que j'ai l'intention de faire est de trouver tous les différents classements, etc. des éléments présélectionnés de chaque table de données. –

Répondre

1

Je ne suis pas tout à fait sûr de ce que vous êtes après, mais quelque chose comme ceci:

select s.name, 
     d1.name as d1_name, 
     d2.name as d2_name 
from shortlist s 
    left join lateral (
    SELECT data1.*, similarity(s.name, data1.name) AS sim 
    FROM data1 
    ORDER BY sim 
    DESC LIMIT 1 
) d1 on true 
    left join lateral (
    SELECT data2.*, similarity(s.name, data2.name) AS sim 
    FROM data2 
    ORDER BY sim DESC 
    LIMIT 1 
) d2 on true 

Tu veux une jointure externe (left join) pour chaque table car sinon vous ne voyez rien s'il n'y a pas de correspondance dans au au moins une des tables.