Запрос Rails Postgres, выбирающий только элементы, которые отображаются во всех поисковых параметрах с ассоциациями - PullRequest
4 голосов
/ 10 марта 2019

Я хочу создать запрос Postgres на основе нескольких параметров выбора пользователя.

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

Например, пользователь выбирает дату начала 2014 года и дату окончания 2018. Элемент банановых функций ввсе эти годы, но яблоко только в 2014, 2015 и 2017 годах. Поэтому мой конечный результат покажет только среднюю цену на бананы, а не на яблоки.

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

@sale_averages = Sale.joins(:shops, :items).where('extract(year from season_year) < ? AND extract(year from season_year) > ? ', params[:start_year], params[:end_year])
.where('shops.name = ?', params[:select_shop])
.select('items.name, AVG(sale.price) as price').group('shop.name')

Схема

create_table "items", force: :cascade do |t|
 t.string "name"
end

create_table "sales", force: :cascade do |t|
 t.integer "shop_id"
 t.integer "item_id"
 t.date "season_year"
 t.decimal "price"
end

create_table "shops", force: :cascade do |t|
 t.string "name"
end

1 Ответ

7 голосов
/ 12 марта 2019

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

 number_years = params[:end_year].to_i - params[:start_year].to_i + 1
 @sale_averages = Sale.joins(:shops, :items)
                      .select('items.name, AVG(sale.price) as price')
                      .where("EXTRACT(year from season_year) BETWEEN #{params[:start_year]} AND #{params[:end_year]}")
                      .where('shops.name': params[:select_shop])
                      .group('items.name')
                      .having("(COUNT(DISTINCT(EXTRACT(year from season_year))) = #{number_years})")

Я также использовал BETWEEN вместо <и >.Я думаю, что вы хотите группировать по названию товара, а не по магазину (как это было в исходном запросе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...