Rails Postgres 查询,仅选择出现在所有具有关联的搜索参数中的项目

Rails Postgres query, selecting only items that appear in all search params with associations

我想创建一个基于一些用户 select 参数的 Postgres 查询。

用户将 select 一家商店以及开始和结束年份。提交后,我只想显示仅存在于所有年份的商品的平均价格 selected.

例如,用户 selects 的开始日期为 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

您可以查看每年有哪些项目有记录。您可以通过检查每个项目的不同年份数是否等于年份总数(使用 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 而不是 <>。 我认为您想按商品名称而不是商店进行分组(因为它在您的原始查询中)。