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

时间:2019-03-10 01:45:52

标签: ruby-on-rails postgresql ruby-on-rails-5

我正在基于一些用户选择参数创建一个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 个答案:

答案 0 :(得分:7)

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