Подзапросы и последовательность агрегатных функций

#sql #postgresql

#sql #postgresql

Вопрос:

У меня есть две таблицы: команды и игроки. Игроки играют в командах.

Команды:

 team_id  team_name  region
1        Spain      Asia
  

Игроки:

 team_id  player_id  age
1        1          27
  

Мне нужно выяснить, из какого региона самая молодая команда. Итак, поэтапно мне нужно выяснить средний возраст в каждой команде, затем минимальное из этих значений, а затем выбрать регион с этим минимумом.

Я написал запрос, и он работает, только если вычисленное минимальное среднее значение уникально:

 select teams.id, region, avg(age) as average from teams
inner join players_stat on teams.id=players_stat.id
group by teams.id, region
order by average asc
limit 1
  

Но я не знаю, как написать краткий запрос, если у меня одинаковый минимальный возраст для более чем одной команды из разных регионов. Я пытался использовать до 3 подзапросов, но не нашел эффективного способа. Что больше всего расстраивает, так это то, что следующий код дает мне желаемый минимальный возраст

 select min(a.average) from
    (select teams.id, region, avg(age) as average from teams
    inner join players_stat on teams.id=players_stat.id
    group by teams.id, region
    order by average asc) a
  

Но я не могу получить информацию о регионе. Если я включаю ‘region’ сразу после выбора, затем требуется включить его в предложение ‘group by’. Если я это сделаю, он затем вычисляет минимум по регионам.

Пожалуйста, помогите

Ответ №1:

Не включайте информацию о регионе до тех пор, пока не будет вычислен минимум avg(age) . Чтобы поддерживать все команды в случае ничьей, используйте rank() функцию.

 with team_avg as (
  select team_id, avg(age) as avg_age,
         rank() over (order by avg(age)) as team_rank
    from players
   group by team_id
)
select t.*, a.avg_age
  from teams t
       join team_avg a
         on a.team_id = t.team_id
 where a.team_rank = 1;
  

Комментарии:

1. Спасибо! Я должен взглянуть на эту функцию rank() .

Ответ №2:

Ваш первый запрос кажется прекрасным. Я бы написал это, используя псевдонимы таблиц:

 select t.id, t.region, avg(ps.age) as average
from teams t join
     players_stat ps
     on t.id = ps.id
group by t.id, t.region
order by average asc
limit 1
  

Комментарии:

1. Спасибо, но что, если у меня есть две команды из разных регионов со средним возрастом «32», например, я не могу поставить «ограничение 1»