GROUP BY 和 ORDER BY 问题

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)

我想返回cmap5ts_rank()函数排序的主表中所有行的名称匹配,但对于cmap5我想要的每一行:

  • cid为每个查询选择最好的 X s ( group by cid)
  • 或者 ORDER BY my results as 1+ts_rank/count(cid)

为了获得最佳匹配,我尝试添加select distinct on c.name,但是当排名相同时,我希望获得cid更多匹配的查询。我尝试在查询结束时添加一个简单的组,但出现错误,我该怎么做?

添加评论:

一方面,对于那些排名相同的结果,例如。上面52830355311211,获得5311211最高结果,因为它的cid点击次数比 多5283035,所以我有点想考虑排名中的点击次数 / cid,例如 final_rank = 1+ts_rank(cid)/no。命中数(cid)。

另一方面,我想获取X每个查询名称的第一个cid。如果我使用LIMIT X它返回X整个查询表的第一个结果,而不是我想要的查询表的X 每个名称(行)的第一个结果。

Erw*_*ter 9

首先,您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.nameDISTINCT ON(SQL标准的Postgres的特定扩展DISTINCT),采取先最高等级和,同一等级内,创同行计数。看:

  • 选择每个 GROUP BY 组中的第一行?

在一个查询级别中组合GROUP BYDISTINCT ON这种方式是可能的,因为DISTINCTDISTINCT ON之后 应用GROUP BY