Группировка нескольких строк в одну строку postgres для каждой позиции в select - PullRequest
0 голосов
/ 10 ноября 2019

У меня есть таблица 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;

Работает нормально. Но теперь я хотел бы изменить этот запрос так, чтобы я получил два столбца и строку для каждого существующего университета в таблице: первый столбец будет названием университета, а второй - тремя наиболее похожими университетами, найденными в базе данных (илиесли проще - четыре колонки, где первая - это университет, а следующие три - самые похожие).

Как должно выглядеть это утверждение?

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Вы можете использовать встроенный агрегированный запрос:

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).

0 голосов
/ 10 ноября 2019

Я думаю, что боковое объединение и агрегация делают то, что вы хотите:

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.

...