mca*_*rox 7 postgresql aggregate full-text-search group-by greatest-n-per-group
我有两张这样的表:
CREATE TABLE cmap5 (
name varchar(2000),
lexemes tsquery
);
Run Code Online (Sandbox Code Playgroud)
和
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)
);
Run Code Online (Sandbox Code Playgroud)
我目前的查询是:
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
Run Code Online (Sandbox Code Playgroud)
输出是:
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
Run Code Online (Sandbox Code Playgroud)
我想返回cmap5
按ts_rank()
函数排序的主表中所有行的名称匹配,但对于cmap5
我想要的每一行:
cid
为每个查询选择最好的 X s ( group by cid
)ORDER BY my results as 1+ts_rank/count(cid)
为了获得最佳匹配,我尝试添加select distinct on c.name
,但是当排名相同时,我希望获得cid
更多匹配的查询。我尝试在查询结束时添加一个简单的组,但出现错误,我该怎么做?
添加评论:
一方面,对于那些排名相同的结果,例如。上面5283035
和5311211
,获得5311211
最高结果,因为它的cid
点击次数比 多5283035
,所以我有点想考虑排名中的点击次数 / cid
,例如 final_rank = 1+ts_rank(cid)/no。命中数(cid)。
另一方面,我想获取X
每个查询名称的第一个cid。如果我使用LIMIT X
它返回X
整个查询表的第一个结果,而不是我想要的查询表的X
每个名称(行)的第一个结果。
首先,您PRIMARY KEY
跨越两varchar(2000)
列似乎非常昂贵。如果您将 PK 用于其他任何用途,我建议使用代理 PK(使用serial
列)并添加UNIQUE
约束以强制(cid, name, synonym)
.
如果您的某一varchar
列实际使用了最大长度,则您将超过索引条目的最大大小。看:
我想你想要的是这个,因为它是有道理的:
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;
Run Code Online (Sandbox Code Playgroud)
我使用[INNER] JOIN
带有附加连接条件的显式替换您的CROSS JOIN
加号WHERE
子句。它通常被认为是优越的(更容易阅读和调试)。我也使用rnk
作为列名来避免基本函数名rank
作为标识符。
c.name
将具有相同rnk
和的结果分组s.cid
,采取min(s.synonym)
(由于问题中缺乏定义)以及count(*)
每组的同级。
减少一排每c.name
用DISTINCT ON
(SQL标准的Postgres的特定扩展DISTINCT
),采取先最高等级和,同一等级内,创同行计数。看:
在一个查询级别中组合GROUP BY
和DISTINCT ON
这种方式是可能的,因为DISTINCT
或DISTINCT ON
在之后 应用GROUP BY
。
归档时间: |
|
查看次数: |
44069 次 |
最近记录: |