J'ai deux tableaux comme celui-ci:
CREATE TABLE cmap5 (
name varchar(2000),
lexemes tsquery
);
et
CREATE TABLE IF NOT EXISTS synonyms_all_gin_tsvcolumn (
cid int NOT NULL, -- REFERENCES pubchem_compounds_index(cid)
name varchar(2000) NOT NULL,
synonym varchar(2000) NOT NULL,
tsv_syns tsvector,
PRIMARY KEY (cid, name, synonym)
);
Ma requête actuelle est:
SELECT s.cid, s.synonym, c.name, ts_rank(s.tsv_syns,c.lexemes,16)
FROM synonyms_all_gin_tsvcolumn s, cmap5 c
WHERE c.lexemes @@ s.tsv_syns
Et la sortie est:
cid | synonym | name (query) | rank
5474706 | 10-Methoxyharmalan | 10-methoxyharmalan | 0.0901673
1416 | (+/-)12,13-EODE | 12,13-EODE | 0.211562
5356421 | LEUKOTOXIN B (12,13-EODE) | 12,13-EODE | 0.211562
180933 | 1,4-Chrysenequinone | 1,4-chrysenequinone | 0.211562
5283035 | 15-Deoxy-delta-12,14-prostaglandin J2 | 15-delta prostaglandin J2 | 0.304975
5311211 | 15-deoxy-delta 12 14-prostaglandin J2 | 15-delta prostaglandin J2 | 0.304975
5311211 | 15-deoxy-Delta(12,14)-prostaglandin J2| 15-delta prostaglandin J2 | 0.304975
5311211 | 15-Deoxy-delta-12,14-prostaglandin J2 | 15-delta prostaglandin J2 | 0.304975
5311211 | 15-Deoxy-delta 12, 14-Prostaglandin J2| 15-delta prostaglandin J2 | 0.304975
Je voudrais renvoyer les correspondances de noms de toutes les lignes de cmap5
Dans ma table principale classées par la fonction ts_rank()
mais pour chaque ligne de cmap5
Je veux:
cid
s pour chaque requête (group by cid
)ORDER BY my results as 1+ts_rank/count(cid)
Pour obtenir la meilleure correspondance, j'ai essayé d'ajouter select distinct on c.name
, Mais lorsque le rang est le même, je veux obtenir le cid
avec plus de correspondances à la requête. J'ai essayé d'ajouter un groupe simple à la fin de la requête mais j'obtiens une erreur, comment faire?
Commentaires ajoutés:
D'une part pour les résultats dont le rang est le même, par exemple. au-dessus de 5283035
et 5311211
, obtenez 5311211
comme résultat supérieur parce que cid
a plus de hits que 5283035
, donc je veux en quelque sorte prendre en compte le nombre de hits/cid
dans le classement, comme final_rank = 1 + ts_rank (cid)/no. de coups (cid).
D'un autre côté, je veux obtenir les premiers X
cids par nom de requête. Si j'utilise LIMIT X
, Il renvoie les premiers X
résultats de la table de requête entière, pas le premier X
par nom (ligne) de la requête table comme je veux.
Tout d'abord, votre PRIMARY KEY
Sur deux colonnes varchar(2000)
semble extrêmement cher. Si vous utilisez votre PK pour autre chose, je suggère un PK de substitution (utilisez une colonne serial
) et ajoutez une contrainte UNIQUE
pour appliquer l'unicité sur (cid, name, synonym)
.
Si l'une de vos colonnes varchar
utilise réellement la longueur maximale, vous dépasseriez la taille maximale pour une entrée d'index. Voir:
Je suppose ce que vous voulez, c'est parce que cela aurait du sens:
SELECT DISTINCT ON (c.name)
c.name, min(s.synonym) AS min_synonym, s.cid
, ts_rank(s.tsv_syns, c.lexemes, 16) AS rnk
, count(*) AS ct
FROM synonyms_all_gin_tsvcolumn s
JOIN cmap5 c ON c.lexemes @@ s.tsv_syns
GROUP BY c.name, rnk, s.cid
ORDER BY c.name, rnk DESC, ct DESC;
J'utilise [INNER] JOIN
Explicite avec une condition de jointure jointe remplaçant votre CROSS JOIN
Plus WHERE
clause. Il est généralement considéré comme supérieur (plus facile à lire et à déboguer). J'utilise également rnk
comme nom de colonne pour éviter le nom de fonction de base rank
comme identifiant.
Regroupez les résultats par c.name
Qui ont les mêmes rnk
et s.cid
, Prenez min(s.synonym)
(faute de définition dans la question) et count(*)
les pairs par groupe.
Réduisez à une ligne par c.name
Avec DISTINCT ON
(Extension spécifique Postgres du standard SQL DISTINCT
), en prenant le rang le plus élevé en premier et, dans le même rang, le nombre d'homologues le plus élevé. Voir:
La combinaison de GROUP BY
Et DISTINCT ON
De cette façon dans un niveau de requête est possible car DISTINCT
ou DISTINCT ON
Sont appliqués après GROUP BY
.