I have a product, user and product_click model.
In product_click, I have column count
where I\'m keeping a record, which user click which product how many times
While I am thinking of other ways, one straight way would be a 2 step solution.
product_ids = ProductClick.where(user_id: user.id).order('count desc').pluck(:product_id)
products = Product.where(id: product_ids)
It'll definitely improve your time and is better than your query (which is N+1).
Using preloading
Product.includes(:product_clicks).where('product_clicks.user_id' => user.id).order('product_clicks.count desc')
The above query should also result in the same way, however, it may internally hit 2 queries anyway.
Using having clause - Recommended
Product.includes(:product_clicks).having('product_clicks.user_id' => user.id).order('product_clicks.count desc')
Update - Using OR
Product.includes(:product_clicks).where('product_clicks.user_id' => user.id)
.order('product_clicks.count desc')
.or(
Product.includes(:product_clicks)
.where('product_clicks.user_id' => user.id)
.where(product_clicks: { id: nil })
)