используйте min() и avg () в подзапросе

#sql #db2 #subquery #average #min

#sql #db2 #подзапрос #среднее #min

Вопрос:

Я работаю над db2 из ibm cloud и sql. Мои данные содержат 1 таблицу с 3 столбцами: школы, их общая производительность (уровень) и местоположение. Я хочу найти местоположение с наименьшим СРЕДНИМ уровнем, используя подзапрос с помощью avg и min.

У меня есть этот код, который выполняет эту работу:

 select location, avg(level) as avglevel
from schools_table
group by location
order by avglvl
limit 1;
  

Но я ищу что-то более похожее:

 select location
from schools_table
where level = (select min(level) from schools_table);
  

это дает минимум всех значений. Однако меня интересует минимум среднего значения.

пожалуйста, помогите Большое спасибо за любую информацию.

Артуро

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

1. Что вам не нравится в вашем коде, который использует order by и limit ?

2. Я немного потерялся. У вас есть две таблицы, упомянутые в вопросе. Описание таблицы в тексте не соответствует столбцам, используемым в запросах. Примеры данных и желаемые результаты действительно помогли бы.

3. Привет! Извините, что я перепутал две таблицы, вы правы. Я уже исправил это, и я думаю, что ответ от Фахми — это то, что я искал.

4. @GMB, ты прав, мне особенно не нравится строка limit . Вместо упорядочивания по и ограничения 1 строкой я хотел получить ответ с помощью функции min() .

5. Что, если два местоположения имеют одинаковый средний уровень и оба равны минимальному? Один из них будет потерян, если вы используете limit .

Ответ №1:

Вы можете попробовать следующее —

 with cte as
(
select location,avg(safety_score) as safety_score  from chicago_public_schools group by location
)
select community_area_name
from chicago_public_schools
where safety_score = (select min(safety_score) from cte)
  

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

1. Спасибо! Я думаю, что это все. Я новичок в sql и не знал о операторе with . Просто из любопытства, возможно ли это без него? Как, каким-то образом, сгенерировать эту переменную / новую таблицу cte в подзапросе?

Ответ №2:

Я думаю, вам просто нужно

 select community_area_name
from chicago_public_schools
where safety_score = (select avg(safety_score)
                      from chicago_public_schools 
                      group by location
                      order by avg(safety_score) asc --sort the result
                      limit 1); --pick the smallest avg
  

Теперь .. я не рекомендую это по соображениям производительности, но если вы действительно хотите избежать order by with limit , а также не хотите использовать a cte , вы можете использовать a window function

 select community_area_name
from chicago_public_schools
where safety_score = (select distinct min(avg(safety_score)) over()
                      from chicago_public_schools 
                      group by location)
  

И если вы хотите избежать window functions этого, вы могли бы полагаться исключительно на подзапросы, но тогда — это слишком некрасиво

 select community_area_name
from chicago_public_schools a
join (select min(safety_score) as min_safety_score
      from (select avg(safety_score) as safety_score  
            from chicago_public_schools 
            group by location) b) c on a.safety_score = c.min_safety_score
  

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

1. Привет, спасибо за ответ! Я искал код, который получает наименьшее среднее значение с помощью функции min(). Ваш способ очень похож на тот, который у меня есть в вопросе. Однако вам удается сделать это в подзапросе, который я также нахожу интересным. Еще раз спасибо!

2. @arturo451 Нет проблем, я добавил другую альтернативу для обучения