如何使用具有不同值的联接表获取值?

时间:2019-06-19 13:59:11

标签: sql ruby-on-rails postgresql ruby-on-rails-5 left-join

我有一个产品,用户和product_click模型。 在product_click中,我有一个count列,我在其中记录,哪个用户点击哪个产品多少次。

我尝试过

Product.sort_by{ |r|  r.product_clicks.where(user_id: user.id).first.try(:count).to_i

给出期望的结果,但在运行时创建大量查询。

product_click.rb

belongs_to :product
  belongs_to :user

product.rb

has_many :product_clicks, dependent: :destroy

user.rb

has_many :product_clicks, dependent: :destroy

模式

create_table "product_clicks", force: :cascade do |t|
    t.bigint "product_id"
    t.bigint "user_id"
    t.bigint "count", default: 0
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

在控制器中

Product.left_outer_joins(:product_clicks).order("count DESC NULLS LAST")

现在我正在寻找类似的东西。

但是在这里,我无法检查计数是否属于哪个特定用户。 如果我要添加

Product.left_outer_joins(:product_clicks).where(resource_clicks: { user_id: user.id }).order("count DESC NULLS LAST")

然后显示的是用户点击过的产品,而没有点击过的产品。

我也尝试过

Product.left_outer_joins(:product_clicks).where(product_clicks: { user_id: [user.id, nil] }).order("count DESC NULLS LAST")

但是给我我所单击的所有内容,而所有其他人都没有单击。如果有人点击了我没有点击的内容,那么它不会显示给我

1 个答案:

答案 0 :(得分:0)

虽然我在考虑其他方式,但直接的方法是两步解决方案。

product_ids = ProductClick.where(user_id: user.id).order('count desc').pluck(:product_id)

products = Product.where(id: product_ids)

它肯定会改善您的时间,并且比您的查询(N + 1)要好。

使用预加载

Product.includes(:product_clicks).where('product_clicks.user_id' => user.id).order('product_clicks.count desc')

上面的查询也应该以相同的方式产生结果,但是无论如何它可能在内部命中2个查询。

使用Haveing子句-推荐

Product.includes(:product_clicks).having('product_clicks.user_id' => user.id).order('product_clicks.count desc')