对于选择中的每个位置,将多行分组为一个字符串 postgres

Posted

技术标签:

【中文标题】对于选择中的每个位置,将多行分组为一个字符串 postgres【英文标题】:Grouping multiple rows into one string postgres for each position in select 【发布时间】:2020-03-06 03:41:37 【问题描述】:

我有一个表education,其中有一列university。对于表中的每一行,我想从表中找到 3 所最相似的大学。

这是我的查询,可以找到与给定输入最相似的 3 所大学:

select distinct(university),
               similarity(unaccent(lower(university)),
                          unaccent(lower('Boston university')))
from education
order by similarity(unaccent(lower(university)),
                    unaccent(lower('Boston university'))) desc
limit 3;

它工作正常。但是现在我想修改这个查询,以便为表中的每个现有大学获得两列和一行:第一列是大学名称,第二列是数据库中找到的三所最相似的大学(或如果它更容易 - 四个列,第一个是大学,接下来的 3 个是最相似的)。

这个语句应该是什么样子的?

【问题讨论】:

样本数据和期望的结果真的很有帮助。 【参考方案1】:

您可以使用内联聚合查询:

with u as (select distinct university from education)
select 
    university,
    (
        select string_agg(u.university, ',')
        from u 
        where u.university != e.university
        order by similarity(
            unaccent(lower(u.university)), 
            unaccent(lower(e.university))
        ) desc
        limit 3
    ) similar_universities
from education e

这假设给定的大学可能在教育表中出现不止一次(因此需要 cte)。

【讨论】:

【参考方案2】:

我认为横向连接和聚合可以满足您的需求:

select e.university, e2.universities
from education e cross join lateral
     (select array_agg(university order by sim desc) as universities
      from (select e2.university,
                   similarity(unaccent(lower(e2.university)),
                              unaccent(lower(e.university))
                             ) as sim
            from education e2
            order by sim desc
            limit 3
           ) e2
      ) e2;

注意:最相似的大学可能是同名大学。 (您可以在子查询中使用 where 子句将其过滤掉。)

这会将值作为数组返回,因为我更喜欢在 Postgres 中使用数组而不是字符串。

【讨论】:

以上是关于对于选择中的每个位置,将多行分组为一个字符串 postgres的主要内容,如果未能解决你的问题,请参考以下文章

Oracle sql使用子查询将多行结果分组为一行

sqlServer 多行合并为一行

将 pandas 中的一个单元格拆分为多行

通过对数据框列中的值进行分组来绘制多个图?

python 计算数字中的每个数字和非间隔字符串中的每个字母。将它们分组为字典并打印字典。

AreYouBusy (混合背包)