Метод Rails group, выводящий неверное среднее значение в Postgres

#ruby-on-rails #postgresql

#ruby-on-rails #postgresql

Вопрос:

У меня есть поисковый запрос (с использованием Postgres), который использует несколько параметров поиска и собирает среднюю отдачу от обработок. Проблема, с которой я сталкиваюсь здесь, заключается в том, что среднее значение обработок одинаково для обоих результатов, что неверно. Я не уверен, где я ошибаюсь с этим запросом, но, похоже, он собирает среднее значение для всех и выводит один и тот же результат для каждого обращения:

 @search = Trial.joins(:region, :property, :quality_datum, treatment_selections: :treatment)
.where("EXTRACT(year from season_year) BETWEEN #{params[:start_year]} AND #{params[:end_year]}")
.where('regions.name': params[:select_region]).where('properties.name': params[:select_property])  
.group('treatments.id')
.select('treatments.name, AVG(quality_data.yield) as yield')
  

Который выводит:

 |    Name     | Average |
| Treatment 1 |   8.68  |       
| Treatment 2 |   8.68  |
  

Что неверно, должно быть:

 |    Name     | Average |
| Treatment 1 |   9.27  |       
| Treatment 2 |   7.25  |
  

Quality_data.числа выхода равны:

Обработка 1: 9.86, 9.79, 8.16, при котором среднее значение должно быть равно 9.27

Обработка 2: 10.01, 4.89, 6.85, среднее значение которого должно быть равно 7.25

Вывод запроса:

 SELECT treatments.name, AVG(quality_data.yield) as yield FROM "trials" 
INNER JOIN "regions" ON "regions"."id" = "trials"."region_id" 
INNER JOIN "properties" ON "properties"."id" = "trials"."property_id" 
INNER JOIN "treatment_selections" ON "treatment_selections"."trial_id" = "trials"."id" 
INNER JOIN "quality_data" ON "quality_data"."treatment_selection_id" = "treatment_selections"."id" 
INNER JOIN "treatment_selections" "treatment_selections_trials" ON "treatment_selections_trials"."trial_id" = "trials"."id" 
INNER JOIN "treatments" ON "treatments"."id" = "treatment_selections_trials"."treatment_id" WHERE (EXTRACT(year from season_year) BETWEEN 2016 AND 2018) AND "regions"."name" = $1 AND "properties"."name" = $2 GROUP BY treatments.id
  

Ассоциации

 class Trial
  belongs_to :region
  belongs_to :property
  has_many :treatment_selections, dependent: :destroy
  has_many :quality_datum, through: :treatment_selections
end

class TreatmentSelection < ApplicationRecord
  belongs_to :trial
  belongs_to :treatment
  has_many :quality_datum, dependent: :destroy
end

class Treatment < ApplicationRecord
  has_many :treatment_selections
end

class Region < ApplicationRecord
  has_many :trials
end

class Property < ApplicationRecord
  has_many :trials
end
  

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

1. Насколько я понимаю, ваш запрос к БД сам возвращает неверные данные? Возможно, вы захотите поиграть с консолью базы данных напрямую и проверить, правильный ли диапазон записей, учитываемых вашим запросом.

2. Спасибо @Marek. Хорошее предложение. Это уже давно занимает мою голову, и я не вижу, где что-то не так, надеюсь, ваше предложение может показать, в чем проблема.

Ответ №1:

После попытки нескольких решений в течение нескольких дней у меня возникло подозрение, что treatments.id и treatment_selections.treatment_id не совпадают должным образом.

Я изменил запрос на следующий, и, похоже, он сработал так, как должен:

 @search = Trial.joins(:region, :property, :quality_datum, :treatment_selections)
.joins('INNER JOIN treatments ON treatments.id = treatment_selections.treatment_id')
.select('treatments.name, AVG(quality_data.yield) as yield') 
.group('treatments.id')
.where("EXTRACT(year from season_year) BETWEEN #{params[:start_year]} AND #{params[:end_year]}")
.where('regions.name': params[:select_region]).where('properties.name': params[:select_property])
  

Разница здесь в том, что я принудительно применяю ВНУТРЕННЕЕ объединение к таблицам treatment и treatment_selection с соответствующими идентификаторами.